【dart 学习】 构造函数
dart 构造函数 ClassName(...) //普通构造函数 普通构造函数 这就是我们普通的构造函数,其样子和其它语言几乎一样 class Point { num x, y; Point(num x, num y) { // There's a better way to do this, stay tuned. this.x = x; this.y = y; } } 上例中只有两个成员变量,如果有10个,岂不是麻烦死?所以Dart有语法糖给你哦: class Point { num x, y; // Syntactic sugar for setting x and y // before the constructor body runs. Point(this.x, this.y); } 它可以将x,y的赋值变得简单一些,就不用写构造函数的方法体了,记得括号后用分号哦。 Classname.identifier(...) //命名构造函数 命名构造函数 class Point { num x, y; Point(this.x, this.y); // 命名构造函数,新增代码 Point.origin() { x = 0; y = 0; } } 请记住,命名构造函数不可继承,如果子类想要有 和父类一样的命名构造函数,那就写个同名的(通常也会在子类的命名构造函数里,调用父类的同名命名构造函数) const ClassName(...) //常量构造函数 常量构造函数总结如下几点: 常量构造函数需以const关键字修饰 const构造函数必须用于成员变量都是final的类 构建常量实例必须使用定义的常量构造函数 如果实例化时不加const修饰符,即使调用的是常量构造函数,实例化的对象也不是常量实例 下面结合实例,对以上几点加以说明 正确的常量构造函数定义 根据以上的总结,定义一个Point类,包含一个常量构造函数,注意其成员变量都是final类型,且构造函数用const修饰 class Point { final int x; final int y; const Point(this.x, this.y); } 常量构造函数需以const关键字修饰 如下代码定义一个const对象,但是调用的构造方法不是const修饰的,则会报The constructor being called isn't a const constructor.错误 void main() { const point = Point(1, 2); // 报错 } class Point { final int x; final int y; Point(this.x, this.y); } const构造函数必须用于成员变量都是final的类 如下代码中成员变量x为非final,会报Can't define a const constructor for a class with non-final fields.错误 class Point { int x; final int y; const Point(this.x, this.y); } 构建常量实例必须使用定义的常量构造函数 如下代码,定义一个const对象,但是调用的却是非常量构造函数,会报The constructor being called isn't a const constructor.错误 void main() { var point = const Point(1, 2); // 报错 print(point.toString()); } class Point { int x; int y; Point(this.x, this.y); // 非const构造函数 String toString() { return 'Point(${x}, ${y})'; } } 如果实例化时不加const修饰符,即使调用的是常量构造函数,实例化的对象也不是常量实例 如下代码,用常量构造函数构造一个对象,但是未用const修饰,那么该对象就不是const常量,其值可以再改变 void main() { var point = Point(1, 2); // 调用常量构造函数,但是未定义成常量 print(point.toString()); point = Point(10, 20); // 可以重新赋值,说明定义的变量为非常量 print(point.toString()); } class Point { final int x; final int y; const Point(this.x, this.y); String toString() { return 'Point(${x}, ${y})'; } } factroy ClassName(...) //工厂构造函数 工厂构造函数的定义 工厂构造函数是一种构造函数,与普通构造函数不同,工厂函数不会自动生成实例,而是通过代码来决定返回的实例对象. 工厂构造函数的关键字为factory,下面我们用工厂构造函数写一个只能创造一个实例的类. class A{ String name; static A cache; factory A([String name='A']){ if(A.cache===null){ A.cache=new A.newObject(name); } return A.cache; } A.newObject(this.name); } void main(){ A a=new A('HelloWorld'); print(a.name); A b=new A('HelloDart'); print(b.name); print(a===b); } A类具有一个名为cache的静态成员,它将缓存A类的第一个实例. 在工厂构造函数A中,首先判断A.cache是否已经存在实例(即判断是否是第一次实例化),如果存在则返回缓存的实例,不存在则新建一个实例并缓存. A.newObject是一个命名构造函数,用于创建实例. 运行这段代码,会输出 HelloWorld HelloWorld true 其中字符串”HelloWorld”是第一个实例的name成员,在声明变量b时改用了”HelloDart”,但返回的实例的name成员仍然是”HelloWorld”. 再用===运算符判断一下它们是否属于同一个对象,结果为true,变量a和b指向的是同一个对象. 3.8.2 工厂构造函数的特性 工厂构造函数类似于static静态成员,无法访问this指针,所以在工厂构造函数中能处理的任务较为有限. 使用工厂构造函数时往往需要定义一个命名构造函数用来生产实例. 注意点 初始化列表 初始化列表的执行顺序,在整个构造函数的最前面,它除了可以调用父类的构造函数,还可以在构造函数方法体之前,初始化一些成员变量。 // Initializer list sets instance variables before // the constructor body runs. Point.fromJson(Map<String, num> json) : x = json['x'], y = json['y'] { print('In Point.fromJson(): ($x, $y)'); } 尤其是初始化那些final修饰的成员变量时,初始化列表很有用,因为在方法体中,不能给final修饰的成员变量赋值,因为在执行方法体的时候,final修饰的成员变量已经不能变了。这个地方很多人犯错。 import 'dart:math'; class Point { final num x; final num y; final num distanceFromOrigin; Point(x, y) : x = x, y = y, distanceFromOrigin = sqrt(x * x + y * y); } main() { var p = new Point(2, 3); print(p.distanceFromOrigin); } 参考: 链接:https://www.jianshu.com/p/a0ba5f2ac5ce