标签:over ODB which object 实用 决定 pac 静态类 上下文
类
Dart语法样式: https://www.dartlang.org/guides/language/effective-dart/style 语法:https://www.dartlang.org/guides/language/language-tour
概览
重要概念
关键词
注释
变量
内置类型
函数
操作符
流程
异常
类
泛型
库
异步
发电机
可调用的类
分离
类型定义
元数据
Dart是一种具有类和基于mixin的继承的面向对象语言。每个对象
都是一个类的实例
,所有类都来自Object
。 基于Mixin的继承意味着虽然每个类(除了Object)只有一个超类,但是类体可以在多个类层次结构中重用。
特点: 当最左边的操作数为null
时,使用?.
而不是.
避免异常:
构造函数 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 class { num x,y; Point(this .x, this .y); }
默认构造函数 如果未声明构造函数,则会为您提供默认构造函数。默认构造函数没有参数,并在超类中调用无参数构造函数。
构造函数不是继承的 子类不从其超类继承构造函数。没有声明构造函数的子类只有默认(无参数,无名称)构造函数。
命名构造函数(多构造函数) 1 2 3 4 5 6 7 8 Point.origin(){ x = 8 ; y = 9 ; } Point.withVal(this .x, this .y);
注意: 构造函数不是继承的,这意味着超类的命名构造函数不会被子类继承。如果希望使用超类中定义的命名构造函数创建子类,则必须在子类中实现该构造函数。
一个完整的多构造函数写法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 class { num x,y; Point(this .x, this .y); Point.origin(){ x = 8 ; y = 9 ; } Point.withVal(this .x, this .y); }
调用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 void classAboutMethod(){ var pointOrigin = Point(34 ,67 ); print (pointOrigin.x); print (pointOrigin.y); var pointAbout = Point.origin(); print (pointAbout.x); print (pointAbout.y); var pointAboutVal = Point.withVal(11 , 21 ); print (pointAboutVal.x); print (pointAboutVal.y); }
结果为:
调用非默认的超类构造函数 执行顺序如下:
初始化列表
超类的无参数构造函数
主类的无参数构造函数
初始化列表 重定向构造函数 有时构造函数的唯一目的是重定向
到同一个类中的另一个构造函数
。重定向构造函数
的主体是空的
,构造函数调用出现在冒号(:)之后。
1 2 3 4 5 6 7 8 9 class { num x,y; Point(this .x, this .y); Point.alongX(num x) : this (x,0 ); }
调用:
1 2 3 var pointAlongX = Point.alongX(11 );print (pointAlongX.x);print (pointAlongX.y);
结果为:
常量构造函数 如果你想使你的类生成永远不会更改的对象
,则可以使这些对象成为编译时常量
。为此,请 定义 const构造函数
并 确保 所有实例变量
都是final
。
1 2 3 4 5 6 7 class ImmutablePoint { static final ImmutablePoint origin = const ImmutablePoint(0 , 0 ); final num x, y; const ImmutablePoint(this .x, this .y); }
工厂建设者 在不需要总是创建新的实例的情况下可以使用 factory
关键字,例如下面这个例子表示:从缓存中返回对象的构造函数:
注意: 工厂构造函数无权访问this。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 class { num x,y; Point.alongX(num x) : this (x,0 ); static final Map <String , Point> _cache = Map <String , Point>{}; factory Point.name(String name){ if (_cache.containsKey(name)) { return _cache[name]; }else { final point = Point.alongX(9 ); _cache[name] = point; return point; } } }
调用:
1 2 3 4 5 6 7 var pointName = Point.name('Alice' );var pointName2 = Point.name('Alice' );var pointName3 = Point.name('Bob' );print (pointName.hashCode);print (pointName2.hashCode);print (pointName3.hashCode);assert (pointName == pointName2);
结果:
1 2 3 477440163 477440163 461006651
使用class成员
1 2 3 var pointOrigin = Point(34 ,67 );print (pointOrigin.x);print (pointOrigin.y);
当最左边
的操作数为null
时,使用 ?.
而不是 .
避免异常:
1 2 3 4 5 6 7 8 9 pointAbout?.x = 4 ; print ('pointAbout.x is ${pointAbout.x} ' );pointAbout = null ; pointAbout?.x = 4 ;
使用构造函数 一般情况 1 2 3 4 5 6 7 var pointOrigin = Point(34 ,67 );print (pointOrigin.x);print (pointOrigin.y);var pointAbout = Point.origin();print (pointAbout.x);print (pointAbout.y);
注意: 在Dart2中,new
是可选关键字。
常量构造函数 有些类提供常量构造函数
。要使用常量构造函数创建编译时常量,请将const
关键字放在构造函数
名称之前
:
1 var p = const ImmutablePoint(2 , 2 );
如果构造2个相同
的编译时常量
,那么结果是:产生同一个
规范的实例:
1 2 3 4 var a = const ImmutablePoint(1 , 1 );var b = const ImmutablePoint(1 , 1 );assert (identical(a, b));
在常量上下文中,您可以省略
const构造函数或文字之前的内容。例如,查看此代码,该代码创建一个const映射:
1 2 3 4 const pointAndLine = const { 'point' : const [const ImmutablePoint(0 , 0 )], 'line' : const [const ImmutablePoint(1 , 10 ), const ImmutablePoint(-2 , 11 )], };
那么,除了第一次出现的const
外其他所有的const
关键字都可以省略。简写为:
1 2 3 4 5 const pointAndLine = { 'point' : [ImmutablePoint(0 , 0 )], 'line' : [ImmutablePoint(1 , 10 ), ImmutablePoint(-2 , 11 )], };
如果常量构造函数在常量上下文之外
并且在没有const
的情况下调用,则会创建一个非
常量对象:
1 2 3 4 var a = const ImmutablePoint(1 , 1 ); var b = ImmutablePoint(1 , 1 ); assert (!identical(a, b));
获取对象的类型 要在运行时获取对象的类型,可以使用Object
的runtimeType
属性,该属性返回
一个Type对象
。
1 2 var pointAboutVal = Point.withVal(11 , 21 );print ('the type of pointAboutVal is ${pointAboutVal.runtimeType} ' );
结果为:
1 the type of pointAboutVal is Point
实例变量 以下是 声明 实例变量的方法:
1 2 3 4 5 class { num x; num y; num z = 0 ; }
所有未初始化
的实例变量都具有该值null
。
所有实例变量都生成一个隐式getter方法
。非final实例变量也会生成隐式setter方法
。有关详细信息,请参阅Getters和setter。
1 2 3 4 5 6 7 8 9 10 11 class Point { num x; num y; } void main() { var point = Point(); point.x = 4 ; assert (point.x == 4 ); assert (point.y == null ); }
如果初始化声明它的实例变量(而不是构造函数或方法),则在创建实例时设置该值,该实例在构造函数及其初始化列表执行之前。
方法 方法是为对象提供行为的函数。
实例方法 对象的实例方法可以访问实例变量和this。
getters and setters 抽象方法 实例、getter和setter方法可以是抽象的,定义一个接口,但将其实现留给其他类。抽象方法只能存在于抽象类中。
1 2 3 4 5 6 7 8 9 10 11 abstract class Doer {大专栏 Dart-Tour2-类 "line"> void doSomething(); } class EffectiveDoer extends Doer { void doSomething() { } }
抽象类(abstract) 使用abstract
修饰符定义抽象类 - 无法实例化的类
。抽象类对于定义接口非常有用,通常还有一些实现。如果希望抽象类看起来是可实例化
的,请定义工厂构造函数
。
1 2 3 4 5 abstract class Doer { void doSomething(); }
Dart
与 Java
关于 抽象类
的区别:
Dart
:由abstract
关键字修饰的类就是抽象类,由关键字
决定。
Java
:只要一个类中有未实现的方法,这个方法就是抽象类,由方法
决定。
隐式接口(interfaces)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 class Person { final _name; Person(this ._name); String greet(String who) => 'Hello, $who. I am $_name.' ; } class Impostor implements Person { get _name => '' ; String greet(String who) => 'Hi $who. Do you know who I am?' ; } String greetBob(Person person) => person.greet('Bob' );void main() { print (greetBob(Person('Kathy' ))); print (greetBob(Impostor())); }
这里是具体说明一个类实现多个接口的例子:
1 2 3 class Point implements Comparable , Location { }
特点: 这里的interface
接口和java不同
在于:不需要
定义interface
,任何class
都可以被implements
继承类(extends) 同Java
重写成员(@override) 同Java
注意: 要在类型安全
的代码中缩小
方法参数 或 实例变量 的 类型
,可以使用covariant
关键字。
例子:
1 2 3 4 5 6 7 8 9 class Animal { void chase(Animal x) { ... } } class Mouse extends Animal { ... }class Cat extends Animal { void chase(covariant Mouse x) { ... } }
虽然此示例显示covariant
在子类型
中使用,但covariant
关键字可以放在超类
或子类方法
中。通常,超类方法
是放置它的最佳位置
。该covariant
关键字适用于单个参数
,并且在setter和字段上也受支持。
重写操作符 您可以覆盖下表中显示的运算符。
说明: 表达e1 != e2
是!(e1 == e2)
的语法糖。
一个覆盖+
和-
运算符的类的示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 class Vector { final x,y; Vector(this .x, this .y); Vector operator +(Vector v) => Vector(x + v.x,y + v.y); Vector operator -(Vector v) => Vector(x - v.x,y - v.y); } final v = Vector(2 ,2 );print ('x is ${v.x} , y is ${v.y} ' );final w = Vector(4 ,5 );print ('x is ${w.x} , y is ${w.y} ' );var vw = v + w;print ('x is ${vw.x} , y is ${vw.y} ' );
结果为:
1 2 3 x is 2, y is 2 x is 4, y is 5 x is 6, y is 7
noSuchMethod() 可以通过重写noSuchMethod() 可以发现或者对在代码中尝试使用不存在的方法
或者实例变量
作出反应。
1 2 3 4 5 6 7 8 9 class A { void noSuchMethod(Invocation invocation) { print ('You tried to use a non-existent member: ' + '${invocation.memberName} ' ); } }
你不能调用未实现的方法,除非以下一个是真实的:
枚举类型 枚举类型(通常称为枚举或枚举)是一种特殊类,用于表示固定数量
的常量值
。
使用enum
关键字声明枚举类型:
1 enum Color { red, green, black }
枚举中的每个值都有一个index
,从0
开始。如:
1 assert (Color.black.index == 2 );
要获取枚举中所有值的列表
,请使用枚举values
常量。如:
1 2 3 4 List <Color> colors = Color.values;for (var x in colors) { print ('当前的索引为: ${x.index} ,对应着的值为:${x} ' ); }
结果为:
1 2 3 当前的索引为: 0 ,对应着的值为:Color.red 当前的索引为: 1 ,对应着的值为:Color.blue 当前的索引为: 2 ,对应着的值为:Color.black
switch
用法
1 2 3 4 5 6 7 8 9 10 11 12 13 void doSwitch() { var colorSingel = Color.black; switch (colorSingel) { case Color.black: break ; case Color.blue: break ; case Color.red: break ; default : print ('' ); } }
向类添加功能:mixin mixins
是一种在多个类层次结构
中重用类代码
的方法。可以简单的理解为: mixin修饰的类
中定义了多个类
中公用
的变量
和方法
。
mix
是混合的意思
;in
是在……里面
。那么mixin
可以理解为:可以混合在指定类里面
的公用代码块
。用mixin
关键字代替class
关键字来实现一个可扩展的Object类
,且无需声明构造函数 :
mixin
本身可以
是抽象
的,可以定义各种方法属性,也可以是抽象的,等后续类去实现。
mixin使用 要使用 mixin
,请使用with
关键字后跟一个或多个
mixin关键字修饰的类 。以下示例显示了使用有mixins
修饰的类:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 mixin TestMixin { void test() { print ('test' ); } int testInt = 1 ; void test2(); } class Test with TestMixin { test2() { print ('test2' ); } } void main() { Test().test(); print (Test().testInt); Test().test2(); }
注意: mixin
是 Dart 2.1
中引入的对关键字的支持。
mixin与on关键字: 要指定只有
某些类型可以使用mixin
——使用on
来指定所需的超类
,这样你的mixin
可以调用一个它自身没有定义
的方法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 class BaseObject { void method() { print('call method'); } } mixin TestMixin on BaseObject{ void test() { print('test'); } int testInt = 1; void test2() { method(); } } class Test extends BaseObject with TestMixin { } void main() { Test().test(); // test print(Test().testInt); // 1 Test().test2(); // call method }
当使用on
关键字后,则表示该mixin修饰的类
只能在那个类的子类
使用了。
多个mixin 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 mixin TestMixin1 on BaseContext{ var intValue = 1; void mix1() => print('this is from textMixin1'); void printAnother() => sayHello(); } mixin TestMixin2 on BaseContext{ var intValue = 2; void mix2() => print('this is from testMixin2'); void printBye() => sayGoodbye(); } class BaseContext{ void sayHello() => print("BaseContext say hello"); void sayGoodbye() => print('BaseContext say byebye'); } class TestClass extends BaseContext with TestMixin1,TestMixin2{ @override void mix2() { // TODO: implement mix2 super.mix2(); print('this msg is from TestClass!'); } } void main(){ TestClass().mix2(); // this is from testMixin2 this msg is from TestClass! TestClass().mix1(); // this is from textMixin1 TestClass().sayGoodbye(); // BaseContext say byebye TestClass().printAnother(); // BaseContext say hello TestClass().printBye(); // BaseContext say byebye print(TestClass().intValue); // 2 }
在TestMixin1
与TestMixin2
中都声明了一个intValue
变量,但是值不同。在class TestClass extends BaseContext with TestMixin1,TestMixin2
的顺序中,得到的结果是:
即:TestMixin2
中初始化的值。
那么改变一下with
的顺序呢?class TestClass extends BaseContext with TestMixin2,TestMixin1
,结果是:
由此可见:取值的是最后一个with
的类中的值。
类变量和方法 使用static
关键字实现类范围
的变量和方法。
静态变量 静态变量(类变量)
对于类范围
的状态
和常量
很有用:
1 2 3 4 5 6 7 8 class Queue { static const initialCapacity = 16; // ··· } void main() { assert(Queue.initialCapacity == 16); }
注意:
静态变量在使用之前
不会初始化。
遵循样式指南
建议,优先使用lowerCamelCase
作为常量名称
。
静态方法 1 2 3 4 5 6 7 8 9 10 class Point { num x, y; Point(this.x, this.y); static num distanceBetween(Point a, Point b) { var dx = a.x - b.x; var dy = a.y - b.y; return sqrt(dx * dx + dy * dy); } }
注意 :
对于常用或广泛使用的实用程序和功能,请考虑使用顶级函数
而不是静态方法。
您可以使用静态方法作为编译时常量。例如,您可以将静态方法作为参数传递给常量构造函数。
Dart-Tour2-类
标签:over ODB which object 实用 决定 pac 静态类 上下文
原文地址:https://www.cnblogs.com/lijianming180/p/12099654.html