类与对象

静态成员与实例成员

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

构造函数

构造函数名与类名相同:

class Point {
  num x;
  num y;
  Point(num x, num y) {
    this.x = x;
    this.y = y;
  }
}

可以简写为:

class Point {
  num x;
  num y;
  Point(this.x, this.y);
}

实例化:

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

命名构造函数

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

class Point {
  num x;
  num y;
  Point(this.x, this.y);
  // Named constructor
  Point.fromJson(Map json) {
    x = json['x'];
    y = json['y'];
  }
}

实例化:

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

调用超类构造函数

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

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

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

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

class Circle extends Point {
  num r;
  Circle.fromJson(Map data) : super.fromJson(data) {
    r = data['r'];
  }
}

实例化:

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

初始化列表

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

class Circle extends Point {
  num r;
  Circle.fromJson(Map data) :
        r = data['r'],
        super.fromJson(data);
}

警告

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

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

class Point {
  final num x;
  final num y;
  Point(x, y)
      : x = x,
        y = y;
  Point.fromJson(Map json)
    : x = json['x'],
      y = json['y'];
}
class Circle extends Point {
  num r;
  Circle(x, y, this.r): super(x, y);
  Circle.fromJson(Map data) :
        r = data['r'],
        super.fromJson(data);
}

重定向构造函数

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

class Point {
  num x;
  num y;
  // The main constructor for this class.
  Point(this.x, this.y);
  // Delegates to the main constructor.
  Point.alongXAxis(num x) : this(x, 0);
}

运算符重载

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

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

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

class Vector {
  final int x;
  final int y;
  const Vector(this.x, this.y);
  /// Overrides + (a + b).
  Vector operator +(Vector v) {
    return new Vector(x + v.x, y + v.y);
  }
  /// Overrides - (a - b).
  Vector operator -(Vector v) {
    return new Vector(x - v.x, y - v.y);
  }
}
main() {
  final v = new Vector(2, 3);
  final w = new Vector(2, 2);
  print(v + w) // v + w == (4, 5)
  print(v - w) // v - w == (0, 1)
}

MIT Licensed | Copyright © 2018-present 滇ICP备16006294号

Design by Quanzaiyu | Power by VuePress