Dart构造函数
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
- 点赞
- 收藏
- 关注作者
评论(0)