默认构造函数(无参)

不声明任何构造函数,创建的class会初始化一个默认的构造函数。

  1. class Person {
  2. //里面包含了一个默认的构造函数 Person(){}
  3. }

当声明了构造函数,也就没有默认的构造函数了。如果声明了一个私有的构造函数,那就为创造单例提供了路子。

Dart里面的构造方法写法多样:

传统构造函数(类比java中的带参数的构造方法)

通过构造函数对变量完成初始化, 下面这种写法和Java语法近乎一样

  1. class Person {
  2. String name;
  3. int age;
  4. Person(String name, int age) {
  5. this.name = name;
  6. this.age = age;
  7. }
  8. }

和Java不一样的是,还可以这样写:

  1. class Person {
  2. String name;
  3. int age;
  4. //貌似这种初始化变量的写法才是Dart纯血
  5. Person (this.name, this.age);
  6. }

这种语法糖写法效果和上面一样,但是需要注意的是,Dart不支持无名称(java也没有这个概念)的构造函数重载
要想实现类似重载重载的效果,Dart提供了命名构造函数。

命名构造函数

Java里面没有这玩意,他的语法是(类名.方法名), 要实现上述带参数的无名称构造方法,可以这样写:

  1. class Person {
  2. String name;
  3. int age;
  4. Person.fromNameAndAge(this.name, this.age) : assert(age > 0) {
  5. //貌似这种初始化变量的写法才是Dart纯血
  6. }
  7. }

这种方法有这样几个坑:

  • 对类变量的初始化,只能放在命名里面,也就是fromNameAndAge(this.name, this.age),不能放在方法体;
  • 在命名构造函数右边,也就是冒号右边,跟了一串表达式,在Dart里面叫初始化列表;

初始化列表可以做这些(不一定全):

  1. 调用父类的命名构造方法
  1. class Person {
  2. String name;
  3. int age;
  4. Person.fromNameAndAge(this.name, this.age) : assert(age > 0) {
  5. // parent named constructor
  6. }
  7. }
  8. class Tom extends Person {
  9. Tom.fromNameAndAge (super.name, super.age) : super.fromNameAndAge();
  10. }
  1. 初始化变量
  1. class Point {
  2. int x;
  3. int y;
  4. Point.fromMap(Map<String, int> data) : x = data['x']!, y = data['y']! {
  5. //
  6. }
  7. }
  1. 重定向构造函数

重定向构造函数

这个在Java里面是不是类似重载?,emmm和Java相比还是有点新花样,思考一下,这样玩的优点是什么,还是只是语言新个性。

  1. class Point {
  2. int x;
  3. int y;
  4. Point(this.x, this.y);
  5. //重定向过去就没有自己的方法体了
  6. Point.fromY(int y) : this(0, y);
  7. }

工厂构造函数

这个是不是已经超出了构造函数的队伍,但是需要深刻注意的是,构造函数返回的是该类的一个实例,这个实例可能是cache中的,也可能是新创建的。如何自定义的选择,使用工厂的这种模式,提供了算是Dart语言里面不算新花样的语言特性写法。

Dart提供了一个关键字factory,使用该关键字标记的函数叫做工厂构造函数,这个关键字可以放在无名或者有名字的构造函数上。

  1. class Teacher {
  2. final String name;
  3. static final Map<String, Teacher> _teachers = <String, Teacher>{};
  4. factory Teacher(String name) {
  5. return _teachers.putIfAbsent(name, () => Teacher._newTeacher(name));
  6. }
  7. factory Teacher.fromJson(Map<String, Object> json) {
  8. return Teacher(json['name'].toString());
  9. }
  10. Teacher._newTeacher(this.name);
  11. }

加上了这个factory关键字后,区别于不加,他多了一个return,强行指定了返回的对象是哪个。
其实,也很简单!,But 工厂构造函数不能使用this

常量构造函数

  1. class Point {
  2. static const int x = 0;
  3. final int y;
  4. const Point(this.y);
  5. const Point.fromY(int y) : this(y);
  6. }
  7. main() {
  8. Point point = new Point(0);
  9. Point point1 = const Point(0);
  10. Point point2 = const Point.fromY(0);
  11. Point point3 = const Point.fromY(1);
  12. print(point.hashCode);
  13. print(point1.hashCode);
  14. print(point2.hashCode);
  15. print(point3.hashCode);
  16. }
  17. ---print---
  18. 618489939
  19. 991380737
  20. 991380737
  21. 342902289

按照某些网上大佬所言:

  • const构造函数实际创建一个编译时常量对象
  • 将“ new”与const构造函数一起使用,它仍然会创建一个对象,但是它将只是一个普通的新对象,而不是编译时常量值。

其它


构造函数初始化顺序

  1. 调用初始化列表
    所思:为什么叫初始化列表呢?
    Point(this.y)是不是Point(y):y=y的语法糖?
  2. 调用父类的构造函数
  3. 调用自己的构造函数