接口

接口(interface)即代码之间的契约。 本章节将结合示例讨论Dart中的隐式接口接口类纯接口等概念。

隐式接口

广义上一个library暴露一些成员(函数、类、字段、方法等)给另一个library使用,这些暴露的成员便组成了接口。Dart的普通类隐式地定义了一个接口。

// ex521.dart
class Vehicle {
  void moveForward(double meters) {
    print('moving forward $meters meters');
  }
}

class Car implements Vehicle {
  @override
  void moveForward(double meters) {
    // TODO: implement moveForward
  }
}

此例中 Car 实现了 Vehicle , 因此它必须重写 moveForward(double) 方法,否则无法通过编译。Vehicle 隐式地定义了如下接口:

abstract interface class IVehicle {
  void moveForward(double meters);
}

abstract interface class 表示纯接口,概念上与Java中的interface对应。

接口类

使用 interface class 创建一个接口类(或简称接口)。

// ex522.dart
interface class Vehicle {
  void moveForward(double meters) {}
}

外部library中的类可以实现接口类,但不能继承接口类。

// ex523.dart
import './ex522.dart';

class Car implements Vehicle {
  @override
  void moveForward(double meters) {
    // TODO: implement moveForward
  }
}

// Error: The class 'Vehicle' can't be extended outside of its library
// because it's an interface class.
class Truck extends Vehicle {}

实现接口类,意味着要重写接口类定义的所有公开的实例方法。不能继承接口类,意味着无法通过 super关键字调用接口类定义的实例方法。接口类保证了:

  • 实现类的某个实例方法A,通过this关键字调用另一个实例方法B时,A与B始终位于同一个library中;
  • 实现类无法通过super调用接口类中的实例方法,接口类里的实例方法的具体实现不直接影响实现类,这减少了脆弱基类问题(fragile base class problem)

纯接口

纯接口即抽象接口类(abstract interface class),它的实例方法通常是抽象方法,即只有方法签名没有具体实现。

// ex524.dart
abstract interface class Vehicle {
  void moveForward(double meters);
}

纯接口中的实例方法只能是抽象方法吗?答案是否定的。

abstract interface class Vehicle2 {
  void moveForward(double meters);

  void moveBackward(double meters) {
     print('move backward $meters meters');
  }
}