标签: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