最常见的构造函数形式,即生成构造函数,创建一个类的新实例:
class Point {
num x, y; //Dart中int和double是num的子类
//this引用当前类对象
Point(num x, num y) {
this.x = x;
this.y = y;
}
}
使用语法糖的时候可以这样定义:
class Point {
num x, y;
//用于设置x和y的语法糖
//在构造函数体运行之前
Point(this.x, this.y);
@override
String toString() {
return ("x: $x, y: $y");
}
}
//print(new Point(100, 200)); -> 打印 x: 100, y: 200
默认构造函数
如果未声明构造函数,则会提供默认构造函数。 默认构造函数没有参数,并在调用父类无参数构造函数。
class Parent{
Parent(){
print('In Parent\'s constructor.');
}
}
class Child extends Parent{
Child(){
print('In Child\'s constructor.');
}
}
//new Child(); -> 打印 In Parent's constructor. In Child's constructor.
构造函数不能继承
子类不能继承其父类构造函数,一个没有声明构造函数的子类只有默认(无参数,无名称)构造函数
命名构造函数
当我们需要定义一个有特别含义的构造函数的时候,可以通过构造函数.XXX来命名构造函数
class Point{
num x;
num y;
Point(this.x, this.y);
//创建一个坐标原点类
Point.origin(){
this.x = 0;
this.y = 0;
}
//创建一个坐标为(100, 100)的类
Point.coordinate100(){
this.x = 100;
this.y = 100;
}
@override
String toString() {
return ("x: $x, y: $y");
}
}
调用父类构造函数
默认情况下,子类中的构造函数调用父类的未命名无参数构造函数。 父类的构造函数在子类构造函数体的开头被调用。 如果还使用初始化了列表,则会在调用父类构造函数之前执行。 执行顺序如下:
- 初始化列表
- 父类的无参数构造函数
- 子类的无参数构造函数
如果父类没有未命名的无参数构造函数,则必须手动调用父类中的一个构造函数。 在子类的构造函数体之后用冒号(:)指定父类构造函数
例1:默认先调用父类的无参数构造函数
class Parent{
Parent(){
print('In Parent\'s constructor.');
}
}
class Child extends Parent{
Child(num x, num y) {
print('In Child\'s constructor.');
}
}
//new Child(100, 100); -> 打印
//In Parent's constructor.
//In Child's constructor.
例2:手动调用父类其他构造函数
class Parent{
num x;
num y;
Parent(this.x, this.y){
print('In Parent\'s constructor.');
}
}
class Child extends Parent{
Child(num x, num y) : super(x, y){
print('In Child\'s constructor.');
}
}
//new Child(100, 100); -> 打印
//In Parent's constructor.
//In Child's constructor.
关于初始化列表:
调用父类构造函数之前,可以在构造函数体执行之前初始化示例变量,用逗号分隔,该过程叫初始化列表。
class Parent{
num x;
num y;
num sum;
Parent(num px, num py) : x = px, y = py, sum = px + py{
print("x: $x, y: $y, sum: $sum");
print('In Parent\'s constructor.');
}
}
class Child extends Parent{
Child(num x, num y) : super(x, y){
print('In Child\'s constructor.');
}
}
// new Child(100, 100); -> 打印
//x: 100, y: 100, sum: 200
//In Parent's constructor.
//In Child's constructor.
重定向构造函数
有时构造函数需要重定向到同一个类中的另一个构造函数,在冒号后面用this:
class Point {
num x, y;
//类的主构造函数
Point(this.x, this.y);
//重定向到主构造函数
Point.alongXAxis(num x) : this(x, 0);
}
常量构造函数
如果你的类需要成为永远不会更改的对象,则可以使这些对象成为编译时常量。 定义const构造函数要确保所有实例变量都是final。
class Point {
final num x;
final num y;
static final Point2 origin = const Point2(0, 0);
//const关键字放在构造函数名称之前,且不能有函数体
const Point2(this.x, this.y);
}
没有定义final时提示:
使用函数体时提示:
工厂构造函数
在实现不用总是创建新的类对象的时候,可以使用factory关键字。 例如,工厂构造函数可能从缓存中返回实例,或者它可能返回子类型的实例:
class Logger {
final String name;
bool mute = false;
//工厂构造函数无法访问this,所以这里要用static
//维护一个缓存的Map对象,
static final Map _cache =
{};
//调用该构造函数的时候,会从Map中取出对象
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);
}
}
//调用
var logger = Logger('UI');
logger.log('Button clicked');