文章目录
Dart中的类和单例模式
先了解Dart中的类:
Dart
也是一门面向对象的开发语言,面向对象中非常重要的概念就是类,通过类的初始化创建一个对象
Dart 是支持基于 mixin 继承机制的面向对象语言,所有对象都是一个类的实例,而除了 Null
以外的所有的类都继承自 Object
类。 基于 mixin 的继承 意味着尽管每个类(top class Object?
除外)都只有一个超类,一个类的代码可以在其它多个类继承中重复使用。 扩展方法 是一种在不更改类或创建子类的情况下向类添加功能的方式。
类的定义
- 在
Dart
中,定义类用class
关键字 - 类通常有两部分组成:成员(member)和方法(method)。
- 当未指明其父类的时候, 默认是继承自
Object
的, 定义类的伪代码如下:
class 类名 {
类型 成员名;
返回值类型 方法名(参数列表) {
方法体
}
}
- 在
Dart
语言中, 在类中使用属性(成员/实例变量)时, 有必要时是通过this
获取的 - 但是下面在
getsize
方法中并没有加this
- 这里需要注意的是:
Dart
的开发风格中,在方法中通常使用属性时,会省略this
,但是有命名冲突时,this
不能省略
// 创建类
class Point {
// 定义变量
int x;
void getsize() {
print('x = $x');
}
}
// 类的初始化
main(List<String> args) {
// 从Dart2开始,new关键字可以省略
var point = new Point();
point.x = 1;
point.getsize();
}
使用类的成员
对象的 成员 由函数和数据(即 方法 和 实例变量)组成。方法的 调用 要通过对象来完成,这种方式可以访问对象的函数和数据。
使用(.
)来访问对象的实例变量或方法:
var p = Point(2, 2);
// Get the value of y.
assert(p.y == 2);
// Invoke distanceTo() on p.
double distance = p.distanceTo(Point(4, 4));
使用 ?.
代替 .
可以避免因为左边表达式为 null 而导致的问题:
// If p is non-null, set a variable equal to its y value.
var a = p?.y;
构造函数
- 当通过类创建一个对象时,会调用这个类的构造方法
- 在
Dart
语言中,如果类中没有明确指定构造方法时,将默认拥有一个无参的构造方法() - 上面得到的
point
对象调用的就是默认的无参构造方法
- 在
- 也可以根据自己的需求自定义构造方法
- 当我们创建了自己的构造方法时,默认的无参的构造方法将会失效,不能使用,否则会报错
- 因为
Dart
本身不支持函数的重载, 所以如果我们明确的写一个默认的构造方法,就会和我们自定义的构造方法冲突
class Student {
String name;
int age;
Student(String name, int age) {
this.name = name;
this.age = age;
}
}
- 在上面构造方法中主要实现的就是通过构造函数的参数给类的户型赋值
- 为了简化这一过程,
Dart
提供了一种更加简洁的语法糖形式
class Student1 {
String name;
int age;
// 这里和上面的Studeng的构造方法等价
Student1(this.name, this.age);
}
命名构造方法
- 在实际开发中, 很明显一个构造方法的确是不够我们使用的
- 而且
Dart
又不支持函数的重载, 不能创建爱你相同名称不同参数的构造方法 - 这就衍生出了另外一中构造方法:命名构造方法
class Model {
String name;
int age;
Model(this.name, this.age);
// 命名构造方法
Model.withNameAndAge(String name, int age) {
this.name = name;
this.age = age;
}
// 命名构造方法
Model.initJson(Map<String, Object> map) {
this.name = map['name'];
this.age = map['age'];
}
}
// 初始化对象
main() {
// 普通构造方法
var model0 = Model('name', 12);
// 命名构造方法
var model1 = Model.withNameAndAge('titan', 12);
var model2 = Model.initJson({
'name': 'jun', 'age': 18});
}
初始化列表
几种方式定义的属性都是可变的, 如果定义的属性是final
不可重新赋值的又该如何实现
class Teacher {
final String name;
final int age;
// 1. 这里会有一个错误提示: All final variables must be initialized, but 'age' and 'name' are not
Teacher(String name, int age) {
//2. 这里也会有一个错误提示: 'name' can't be used as a setter because it's final
this.name = name;
this.age = age;
}
}
- 上面第一处错误主要是因为: 在
Dart
中在执行下面{ }
中的代码的时候, 表示Teacher
对象已经初始化完毕了 - 所以在执行
{ }
之前, 必须保证name
和age
被初始化了 - 而且
final
修饰的属性是不可被重新赋值的, 所以才会报错 - 或者也可以使用函数中的命名可选参数处理
class Size {
final double width;
final double height;
final double area;
// 命名可选参数
Size(this.width, this.height, {
this.area = 10 });
}
- 上面通过命名可选参数的形式, 给参数设置默认值也是可以的, 但是不同的是
area
只能设置具体的数值, 不能设置表达式 - 初始化列表的形式不但可以设置具体的数值, 也可以设置默认值为表达式的形式