Dart 笔记 9 - 类(2)

2019-01-15  本文已影响0人  三流之路

抽象类

加 abstract 关键字,抽象方法没有实现体,不需要 abstract 关键字。

abstract class Doer {
  void doSomething(); 
}

class EffectiveDoer extends Doer {
  void doSomething() {
  }
}

隐式接口

每个类都隐式地定义一个接口,该接口包含类的所有实例成员及其实现的任何接口。如果想创建一个类 A,它支持类 B 的 API 而不继承 B 的实现,那么类 A 应该实现 B 接口。

// 有个隐式的接口,包含实例方法 greet().
class Person {
  // In the interface, but visible only in this library.
  final _name;

  // 构造方法不在隐式接口里
  Person(this._name);

  // 在隐式接口里
  String greet(String who) => 'Hello, $who. I am $_name.';
}

// 用实现而不是继承
class Impostor implements Person {
  get _name => '';
  
  // 如果继承必须要有构造方法
  // 实现必须重写 greet 方法
  String greet(String who) => 'Hi $who. Do you know who I am?';
}

String greetBob(Person person) => person.greet('Bob');

void main() {
  print(greetBob(Person('Kathy'))); // Hello, Bob. I am Kathy.
  print(greetBob(Impostor())); // Hi Bob. Do you know who I am?
}

重写方法

子类可以覆盖实例方法、getter 和 setter。可以使用 @override 注解来指示重写了某个成员方法。

class Television {
  void turnOn() {
    _illuminateDisplay();
    _activateIrSensor();
  }
  // ···
}

class SmartTelevision extends Television {
  // 重写方法
  void turnOn() {
    super.turnOn(); // 使用 super 表示父类的方法
    _bootNetworkInterface();
    _initializeMemory();
    _upgradeApps();
  }
  // ···
}

重写操作符

可以重写这些操作符:<+|[]>/^[]=<=~/&~>=*<<==-%>>。类似 Kotlin。

class Vector {
  final int x, y;

  Vector(this.x, this.y);

  Vector operator +(Vector v) => Vector(x + v.x, y + v.y);
  Vector operator -(Vector v) => Vector(x - v.x, y - v.y);
}

void main() {
  final v = Vector(2, 3);
  final w = Vector(2, 2);

  assert(v + w == Vector(4, 5));
  assert(v - w == Vector(0, 1));
}

如果重写 ==,还应该重写对象的 hashCode getter。

hashCode

每个对象自动地提供了一个整数哈希码,因此可以作为映射中的键。但是,重写 hashCode getter 来生成自定义哈希代码。如果这样做,可能还想重写 == 操作符。相等的对象必须具有相同的哈希码。

class Person {
  final String firstName, lastName;

  Person(this.firstName, this.lastName);

  @override
  int get hashCode {
    int result = 17;
    result = 37 * result + firstName.hashCode;
    result = 37 * result + lastName.hashCode;
    return result;
  }

  @override
  bool operator ==(dynamic other) {
    if (other is! Person) return false;
    Person person = other;
    return (person.firstName == firstName &&
        person.lastName == lastName);
  }
}

void main() {
  var p1 = Person('Bob', 'Smith');
  var p2 = Person('Bob', 'Smith');
  var p3 = 'not a person';
  assert(p1.hashCode == p2.hashCode);
  assert(p1 == p2);
  assert(p1 != p3);
}

noSuchMethod()

可以重写 noSuchMethod() 方法来处理程序访问一个不存在的方法或者成员变量:

class A {
  @override
  void noSuchMethod(Invocation invocation) {
    print('You tried to use a non-existent member: ' +
        '${invocation.memberName}');
  }
}

mixins 特性

mixin 类似多继承,但不是子类父类的关系,只是获取了一些功能,可以灵活地混入不同的类来实现不同的功能。相比接口,接口只是获得方法名,不包含实现,而 mixin 包含了实现。

要使用 mixin,在 with 关键字后面加上一个或多个 mixin 名称。

class Musician extends Performer with Musical {
  // ···
}

class Maestro extends Person
    with Musical, Aggressive, Demented {
  Maestro(String maestroName) {
    name = maestroName;
    canConduct = true;
  }
}

要实现 mixin,创建一个 Object 的子类,不声明构造函数,也不调用 super。例如:

abstract class Musical {
  bool canPlayPiano = false;
  bool canCompose = false;
  bool canConduct = false;

  void entertainMe() {
    if (canPlayPiano) {
      print('Playing piano');
    } else if (canConduct) {
      print('Waving hands');
    } else {
      print('Humming to self');
    }
  }
}
上一篇下一篇

猜你喜欢

热点阅读