类(Class)
与Java相同,Dart中所有的类都是Object
的子类。
与Java和Kotlin一样,this
关键字指向当前实例,Dart的代码风格建议省略this,仅在名称冲突等必要的时候使用。
Dart1的对象实例化与Java一样使用new
关键字,Dart2开始可以向Kotlin一样不使用new
创建实例
实例通过instance.runtimeType
可以获取一个类型对象,相当于Java的instance.class
构造函数
构造函数可以有两种形式
ClassName
:类名作为构造函数,像Java、Kotlin一样ClassName.identifier
: 命名的构造函数,类似工厂方法,可以让构造函数的作用更有针对性
var p1 = Point(2, 2);
//Named constructor
var p2 = Point.fromJson({'x': 1, 'y': 2});
当然,这里我们省略了new
关键字,Dart1必须像下面这样:
var p1 = new Point(2, 2);
var p2 = new Point.fromJson({'x': 1, 'y': 2});
Dart的函数不支持重载,所以当需要定义多个构造函数时,有如下两个选择:
- 使用可选参数
- 增加多个命名构造函数
构造参数为成员赋值
Kotlin的构造参数添加var
/val
,可以声明为类的成员变量,并在调用构造函数时直接为其赋值。
Dart与Kotlin类似,通过添加this.
也可以直接为成员赋值,但是成员依然需要单独声明:
class Person {
// 成员变量声明
final String firstName;
final String lastName;
// 调用时直接为成员变量赋值
Person(this.firstName, this.lastName) {
...
}
}
构造函数的继承
像Java一样,没有声明构造函数的子类只有默认的构造函数(无参的类名构造函数),而不会自动继承父类的任何有参构造函数。所以 想调用父类特定构造函数时,需在子类中显示声明一个构造函数并通过super
关键字调用
class Mutant extends Person {
Mutant(String firstName, String lastName) : super(firstName, lastName);
Mutant.anonymous() : super.anonymous() {
print("anonymous mutant");
}
}
重定向构造函数
子类构造函数要么通过super
继承自父类的构造函数,要么通过this
重定向到另一个自己的构造函数,有点类似于类似与Kotlin的次级构造函数指向主构造函数。
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);
}
初始化列表
构造函数体执行之前,通过初始化列表可以进行成员初始化。 各参数的初始化用逗号分隔。
// 在构造函数体执行之前,
// 通过初始列表设置实例变量。
Point.fromJson(Map<String, num> json)
: x = json['x'],
y = json['y'] {
print('In Point.fromJson(): ($x, $y)');
}
final
成员的初始化可以放到初始化列表进行,但是不能放到构造函数体内
class Hoge {
final String fuga;
Hoge(String moge)
: assert(moge != null),
fuga = moge.toUpperCase() {
print(fuga);
}
}
/*
👇放到函数体内的初始化,编译器会报错
class Dame {
final String fuga;
Hoge(String moge) {
fuga = moge.toUpperCase();
}
}
*/
常量构造函数
类成员变量全为final
、且前置了const
关键字的构造函数,我们称为常量构造函数
。
常量构造函数
实例化的对象成为编译时常量。
class Point {
final int x;
final int y;
const Point(this.x, this.y);
}
const p = Point(1, 2);
工厂构造函数
前置factory
关键字后称为工厂构造函数
。
工厂构造函数
与Java的工厂方法类似,需要返回一个类型实例,可以配合缓存实现单例模式。
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);
}
}