一、静态成员与实例成员

  1. class A {
  2. static int num1 = 1; // 静态属性
  3. int num2 = 2; // 实例属性
  4. static int bar() => 10; // 静态方法
  5. int baz() => 20; // 实例方法
  6. }
  7. var a = new A();
  8. print(A.num1); // 1
  9. print(A.bar()); // 10
  10. print(a.num2); // 2
  11. print(a.baz()); // 20

二、构造函数

构造函数名与类名相同:

  1. class Point {
  2. num x;
  3. num y;
  4. Point(num x, num y) {
  5. this.x = x;
  6. this.y = y;
  7. }
  8. }

可以简写为:

  1. class Point {
  2. num x;
  3. num y;
  4. Point(this.x, this.y);
  5. }

实例化:

  1. var p1 = new Point(2, 2);
  2. // 或者
  3. Point p1 = new Point(2, 2);

在 Dart 中 new 关键字可以省略:

  1. var p1 = Point(2, 2);

三、命名构造函数

使用命名构造函数可以为一个类实现多个构造函数, 或者使用命名构造函数来更清晰的表明你的意图:

  1. class Point {
  2. num x;
  3. num y;
  4. Point(this.x, this.y);
  5. // Named constructor
  6. Point.fromJson(Map json) {
  7. x = json['x'];
  8. y = json['y'];
  9. }
  10. }

实例化:

  1. var p2 = new Point.fromJson({"x": 1, "y": 2});
  2. print(p2.x); // 1
  3. print(p2.y); // 2

四、调用超类构造函数

构造函数不能继承,所以超类的命名构造函数 也不会被继承。如果你希望 子类也有超类一样的命名构造函数, 你必须在子类中自己实现该构造函数。

默认情况下,子类的构造函数会自动调用超类的 无名无参数的默认构造函数。 超类的构造函数在子类构造函数体开始执行的位置调用。 如果提供了一个 initializer list(初始化参数列表) ,则初始化参数列表在超类构造函数执行之前执行。 下面是构造函数执行顺序:

  • initializer list(初始化参数列表)
  • superclass’s no-arg constructor(超类的无名构造函数)
  • main class’s no-arg constructor(主类的无名构造函数)

如果超类没有无名无参数构造函数, 则你需要手工的调用超类的其他构造函数。 在构造函数参数后使用冒号 (:) 可以调用超类构造函数。

  1. class Circle extends Point {
  2. num r;
  3. Circle.fromJson(Map data) : super.fromJson(data) {
  4. r = data['r'];
  5. }
  6. }

实例化:

  1. Circle c = Circle.fromJson({"x": 1, "y": 2, "r": 10});
  2. print(c.x); // 1
  3. print(c.y); // 2
  4. print(c.r); // 10

五、初始化列表

在构造函数体执行之前除了可以调用超类构造函数之外,还可以 初始化实例参数。 使用逗号分隔初始化表达式。

  1. class Circle extends Point {
  2. num r;
  3. Circle.fromJson(Map data) :
  4. r = data['r'],
  5. super.fromJson(data);
  6. }

初始化表达式等号右边的部分不能访问 this。

初始化列表非常适合用来设置 final 变量的值:

  1. class Point {
  2. final num x;
  3. final num y;
  4. Point(x, y)
  5. : x = x,
  6. y = y;
  7. Point.fromJson(Map json)
  8. : x = json['x'],
  9. y = json['y'];
  10. }
  11. class Circle extends Point {
  12. num r;
  13. Circle(x, y, this.r): super(x, y);
  14. Circle.fromJson(Map data) :
  15. r = data['r'],
  16. super.fromJson(data);
  17. }

六、重定向构造函数

有时候一个构造函数会调动类中的其他构造函数。 一个重定向构造函数是没有代码的,在构造函数声明后,使用 冒号调用其他构造函数。

  1. class Point {
  2. num x;
  3. num y;
  4. // The main constructor for this class.
  5. Point(this.x, this.y);
  6. // Delegates to the main constructor.
  7. Point.alongXAxis(num x) : this(x, 0);
  8. Point.alongYAxis(num y) : this(0, y);
  9. Point.origin() : this(0, 0);
  10. }

七、运算符重载

下表中的操作符可以被覆写。 例如,如果你定义了一个 Vector 类, 你可以定义一个 + 函数来实现两个向量相加。

  1. < + | [] > / ^ []= <= ~/ & ~ >= * << == – % >>

下面是覆写了 + 和 - 操作符的示例:

  1. class Vector {
  2. final int x;
  3. final int y;
  4. const Vector(this.x, this.y);
  5. /// Overrides + (a + b).
  6. Vector operator +(Vector v) {
  7. return new Vector(x + v.x, y + v.y);
  8. }
  9. /// Overrides - (a - b).
  10. Vector operator -(Vector v) {
  11. return new Vector(x - v.x, y - v.y);
  12. }
  13. }
  14. main() {
  15. final v = new Vector(2, 3);
  16. final w = new Vector(2, 2);
  17. print(v + w) // v + w == (4, 5)
  18. print(v - w) // v - w == (0, 1)
  19. }

八、重写对象的hashCode

在 Dart 中每个对象会默认提供一个整数的哈希值, 因此在 map 中可以作为 key 来使用, 重写 hashCode 的 getter 方法来生成自定义哈希值。 如果重写 hashCode 的 getter 方法,那么可能还需要重写 == 运算符。 相等的(通过 == )对象必须拥有相同的哈希值。 哈希值并不要求是唯一的, 但是应该具有良好的分布形态。。

  1. class Person {
  2. final String firstName, lastName;
  3. Person(this.firstName, this.lastName);
  4. // 重写 hashCode
  5. @override
  6. int get hashCode {
  7. return firstName.hashCode + lastName.hashCode;
  8. }
  9. // 如果重写了 hashCode,通常应该从新实现 == 操作符。
  10. @override
  11. bool operator ==(dynamic other) {
  12. if (other is! Person) return false;
  13. return (other.firstName == firstName && other.lastName == lastName);
  14. }
  15. }
  16. void main() {
  17. var p1 = Person('Bob', 'Smith');
  18. var p2 = Person('Bob', 'Smith');
  19. print(p1.hashCode == p2.hashCode); // true
  20. print(p1 == p2); // true
  21. }