Dart类(构造函数、单例)
构造函数
构造函数类型
-
默认构造函数
类里面没有显示写构造函数,默认是一个隐式的无参构造函数,会优先调用父类的无参构造函数
-
普通构造函数
和JAVA一样,指定一个类名相同的方法就是普通构造函数
class Test{ int a, b; Test(int a, int b){ this.a = a; this.b = b; } }
可以将上述直接简写为
class Test{ int a, b; Test(this.a, this.b); }
-
命名构造函数
命名构造函数就是给构造函数添加个名字,比如从json转model时常用的fromJson就是命名构造函数, 命名构造函数不可以继承
class Test{ int a, b; Test(this.a, this.b); Test.fromJson(int a, int b){ this.a = a; this.b = b; } //同样可以简写 //Test.fromJson(this.a, this.b); }
构造函数调用顺序
隐式调用
默认是首先调用父类无参构造函数,然后子类的无参构造函数
调用顺序
- 初始化列表 (后面有介绍)
- 父类的无参数构造函数
- 子类的无参数构造函数
显式调用
在初始化列表中显示调用父类构造函数
初始化列表
了解调用顺序前,首先明确一下什么是初始化列表, 初始化列表就是构造函数名的冒号: 后面,大括号{ 前面的部分
class Test{
int a, b;heli
Test(): a=1, b=2;//:后 ;前
Test(): a=1, b=2{//或者 :后 {前
}
}
初始化列表的执行顺序,在整个构造函数的最前面,它的作用就是
可以调用父类的构造函数
-
在构造函数方法体之前,初始化一些成员变量
尤其是初始化那些final修饰的成员变量时,初始化列表很有用,因为在方法体中,不能给final修饰的成员变量赋值,因为在执行方法体的时候,final修饰的成员变量已经不能变了。
初始化final变量
-
使用初始化列表, 在:后初始化是可以的
class Test{ final int a, b; Test(): a=1, b=2; }
-
使用构造函数的this也是可以的
class Test{ final int a, b; Test(this.a, this.b); }
下面这种无法初始化final变量,会报错 'a' can't be used as a setter beacuse it's final. 因为在执行方法体的时候,final修饰的成员变量已经不能变了。
class Test{ final int a, b; Test(int a, int b){ this.a = a; this.b = b; } }
构造函数调用可以调用另外构造函数, 但是这种情况下就不能有 {}包住的方法体了,感觉意义不大,目前没领会这种写法有什么用处
class Test{
int a, b;
Test(this.a, this.b);
Test.fromJson(int a): this(a, 2);
}
Dart创建单例
dart创建单例和java思想差不多,static,私有,dart没有private,但是可以用_表示私有,除此之外dart可以借助factory来使正常的Test test = Test()这种写法同样获取单例
class Test{
static Test _instance;//唯一单例, _代表类私有,禁止外部直接访问
factory Test() => _getInstance();//使用工厂构造方法,通过Test()获取类时,返回唯一实例
static Test get instance => _getInstance();//通过静态变量instance获取实例
static Test _getInstance(){//这里真正生成唯一实例
if(_instance==null){
_instance = Test._internal();//命名构造函数初始化唯一实例
}
return _instance;
}
Test._internal(){//命名构造函数
//初始化
}
}
void main() {
Test test1 = Test();//
Test test2 = Test();
Test test3 = Test.instance;
print(test1.hashCode);
print(test2.hashCode);
print(test3.hashCode);
}
控制台输出test1、test2、test3的hashcode,相同
833396152
833396152
833396152