Dart构造函数

举报
yd_221104950 发表于 2020/12/03 00:56:39 2020/12/03
【摘要】 Dart构造函数 1.Dart构造函数的4种格式:1.1.默认构造函数1.2.普通构造函数1.3.命名构造函数1.4.常量构造函数1.5.工厂构造函数 2.构造函数调用父类构造函数的顺序2.1.默认调用父类的无参数构造函数2.2.显式调用父类构造函数2.3.初始化列表 3.构造函数传递 1.Dart构造函数的4种格式: ClassName(...) ...

1.Dart构造函数的4种格式:

ClassName(...) //普通构造函数
Classname.identifier(...) //命名构造函数
const ClassName(...) //常量构造函数
factroy ClassName(...) //工厂构造函数

  
 
  • 1
  • 2
  • 3
  • 4

使用:

var p1 = Point(2, 2); //Dart2中,可以省略构造函数前的new
var p2 = Point.fromJson({'x': 1, 'y': 2});
var p = const ImmutablePoint(2, 2); //常量构造函数,用来创建编译期常量

  
 
  • 1
  • 2
  • 3

1.1.默认构造函数

如果定义了一个类,而没有定义构造函数,那么它将有一个默认的无参构造函数。如果这个类有父类,那么默认构造函数还会调用父类的无参数构造函数。

1.2.普通构造函数

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;
  }
}

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

上例中只有两个成员变量,如果有十几二十个成员变量,那么写起来就很不舒服了!不用怕!Dart有语法糖哦!

class Point {
  num x, y; // Syntactic sugar for setting x and y
  // before the constructor body runs.
  Point(this.x, this.y);
}

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

它可以将x,y的赋值变得简单一些,就不用写构造函数的方法体了,但要记得括号后面要用分号。

1.3.命名构造函数


class Point {
  num x, y; Point(this.x, this.y); // 命名构造函数,新增代码
  Point.origin() { x = 0; y = 0;
  }
}

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

注意:命名构造函数不可继承,如果子类想要有和父类一样的命名构造函数,那就写个同名的(通常也会在子类的命名构造函数里,调用父类的同名命名构造函数)。

1.4.常量构造函数

class ImmutablePoint {
  static final ImmutablePoint origin = const ImmutablePoint(0, 0); final num x, y; const ImmutablePoint(this.x, this.y);
}

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

如果类创建的对象永远不会改变,可以在编译期就创建这个常量实例,并且定义一个常量构造函数,并且确保所有的成员变量都是final的。

1.5.工厂构造函数

工厂构造函数,没有权利访问this。

class Logger {
  final String name;
  bool mute = false; // _cache is library-private, thanks to
  // the _ in front of its name.
  static final Map<String, Logger> _cache = <String, Logger>{}; factory Logger(String name) { if (_cache.containsKey(name)) { return _cache[name]; } else { final logger = Logger._internal(name); _cache[name] = logger; return logger; }
  } Logger._internal(this.name); void log(String msg) { if (!mute) print(msg);
  }
}

main() { var logger = Logger('UI'); logger.log('Button clicked');
}

  
 
  • 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

可能有一种需求,并不需要每次都创建新的类实例,而是每一种情况,只需要一个实例。如上例,类中有一个静态缓存_cache保存着一些Logger类实例,创建实例时,给工厂构造函数传递的name,如果在缓存中已经存在,就用缓存中现成的实例,如果没有,就新建一个实例,并且放到缓存中。
这样一来,可以创建名字为UI / SYS / API 等的实例,然后在debug的时候,如果设置名字为UI的Logger实例的mute为true,就不会打印UI相关的log,而不影响其它两个名字的log。

2.构造函数调用父类构造函数的顺序

如果类继承了父类,那么子类的构造函数一定要调用父类的构造函数,分两种情况:

  • Dart语言自动调用父类的无参数构造函数: 如果没有显式调用父类的构造函数,并且父类有一个无参数构造函数,那么Dart就会帮你在子类的构造函数方法体的最前面,调用父类的无参数构造函数。
  • 代码中显式调用父类的构造函数:如果父类没有无参数构造函数,或者Dart这种隐式调用无法满足你的要求,那就需要显式调用父类的构造函数了

2.1.默认调用父类的无参数构造函数

构造函数分成好几部分来初始化成员变量,调用的顺序如下:
初始化列表 -> 父类的无参数构造函数 -> 子类的无参数构造函数
如果父类没有无参数构造函数,或者Dart这种隐式调用无法满足你的要求,那就需要显式调用父类的构造函数。

2.2.显式调用父类构造函数

显式调用父类构造函数,应该在初始化列表中完成。

class Person {
  String firstName; Person.fromJson(Map data) { print('in Person');
  }
}

class Employee extends Person {
  // Person does not have a default constructor;
  // you must call super.fromJson(data).
  Employee.fromJson(Map data) : super.fromJson(data) { print('in Employee');
  }
}

main() {
  var emp = new Employee.fromJson({}); // Prints:
  // in Person
  // in Employee
}

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23

初始化列表就是构造函数名的冒号后面,打括号前面的部分。

2.3.初始化列表

初始化列表的执行顺序,在整个构造函数的最前面,它除了可以调用父类的构造函数,还可以在构造函数方法体之前,初始化一些成员变量。

// 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)');
}

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

初始化那些final修饰的成员变量时,初始化列表很有用,因为在方法体中,不能给final修饰的成员变量赋值,因为在执行方法体的时候,final修饰的成员变量已经不能变了。

3.构造函数传递

class Point {
  num x, y; // The main constructor for this class.
  Point(this.x, this.y); // Delegates to the main constructor.
  Point.alongXAxis(num x) : this(x, 0);
}

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

传递构造函数,没有方法体,在初始化列表中调用另一个构造函数。

文章来源: blog.csdn.net,作者:WongKyunban,版权归原作者所有,如需转载,请联系作者。

原文链接:blog.csdn.net/weixin_40763897/article/details/108638417

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。