一、静态成员与实例成员
class A {static int num1 = 1; // 静态属性int num2 = 2; // 实例属性static int bar() => 10; // 静态方法int baz() => 20; // 实例方法}var a = new A();print(A.num1); // 1print(A.bar()); // 10print(a.num2); // 2print(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);
在 Dart 中 new 关键字可以省略:
var p1 = Point(2, 2);
三、命名构造函数
使用命名构造函数可以为一个类实现多个构造函数, 或者使用命名构造函数来更清晰的表明你的意图:
class Point {num x;num y;Point(this.x, this.y);// Named constructorPoint.fromJson(Map json) {x = json['x'];y = json['y'];}}
实例化:
var p2 = new Point.fromJson({"x": 1, "y": 2});print(p2.x); // 1print(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 = Circle.fromJson({"x": 1, "y": 2, "r": 10});print(c.x); // 1print(c.y); // 2print(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);Point.alongYAxis(num y) : this(0, y);Point.origin() : this(0, 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)}
八、重写对象的hashCode
在 Dart 中每个对象会默认提供一个整数的哈希值, 因此在 map 中可以作为 key 来使用, 重写 hashCode 的 getter 方法来生成自定义哈希值。 如果重写 hashCode 的 getter 方法,那么可能还需要重写 == 运算符。 相等的(通过 == )对象必须拥有相同的哈希值。 哈希值并不要求是唯一的, 但是应该具有良好的分布形态。。
class Person {final String firstName, lastName;Person(this.firstName, this.lastName);// 重写 hashCode@overrideint get hashCode {return firstName.hashCode + lastName.hashCode;}// 如果重写了 hashCode,通常应该从新实现 == 操作符。@overridebool operator ==(dynamic other) {if (other is! Person) return false;return (other.firstName == firstName && other.lastName == lastName);}}void main() {var p1 = Person('Bob', 'Smith');var p2 = Person('Bob', 'Smith');print(p1.hashCode == p2.hashCode); // trueprint(p1 == p2); // true}
