类修饰符

Last updated: ... / Reads: 33 Edit

类修饰符,除了 abstract ,需要 至少为 3.0 的语言版本。

类修饰符控制类或 mixin 的使用方式,既可以在其自己的库内使用,也可以从库外部使用。 它被定义了。

修饰符关键字位于类或 mixin 声明之前。 例如,写作定义了一个抽象类。 可以在类声明之前出现的完整修饰符集包括:abstract class

  • abstract
  • base
  • final
  • interface
  • sealed
  • mixin

只有修饰符可以出现在 mixin 声明之前。修饰符确实如此 不适用于其他声明,如 、 或 。baseenumtypedefextension

在决定是否使用类修饰符时,请考虑 类,以及类需要能够依赖哪些行为。

如果您维护库,请阅读 API 维护人员的类修饰符页面,以获取有关如何为库导航这些更改的指导。

无修饰符

要允许不受限制地允许从任何库构造或子类型, 使用不带修饰符的 OR 声明。默认情况下,您可以:classmixin

  • 构造类的新实例。
  • 扩展类以创建新的子类型。
  • 实现类或 mixin 的接口。
  • 在 mixin 或 mixin 类中混音。

abstract

定义一个不需要其完整、具体实现的类 整个界面,请使用修饰符。abstract

抽象类不能从任何库构造,无论是它自己的还是 一个外部图书馆。抽象类通常具有抽象方法。

// Library a.dart
abstract class Vehicle {
  void moveForward(int meters);
}
// Library b.dart
import 'a.dart';

// Error: Cannot be constructed
Vehicle myVehicle = Vehicle();

// Can be extended
class Car extends Vehicle {
  int passengers = 4;
  // ···
}

// Can be implemented
class MockVehicle implements Vehicle {
  @override
  void moveForward(int meters) {
    // ...
  }
}

如果你希望你的抽象类看起来是可实例化的, 定义工厂构造函数。

base

要强制继承类或 mixin 的实现,请使用修饰符。 基类不允许在其自己的库之外实现。这保证了:base

  • 每当 类已创建。
  • 所有已实现的私有成员都存在于子类型中。
  • 类中新实现的成员不会中断子类型, 因为所有子类型都继承了新成员。base
  • 除非子类型已声明具有相同名称的成员,否则为 true。 和不兼容的签名。

必须将实现或扩展基类的任何类标记为 、 或 。这样可以防止外部库 破坏基类保证。basefinalsealed

// Library a.dart
base class Vehicle {
  void moveForward(int meters) {
    // ...
  }
}
// Library b.dart
import 'a.dart';

// Can be constructed
Vehicle myVehicle = Vehicle();

// Can be extended
base class Car extends Vehicle {
  int passengers = 4;
  // ...
}

// ERROR: Cannot be implemented
base class MockVehicle implements Vehicle {
  @override
  void moveForward() {
    // ...
  }
}

interface

若要定义接口,请使用修饰符。之外的库 接口自己的定义库可以实现接口,但不能扩展它。 这保证了:interface

当类的一个实例方法调用另一个实例方法时, 它将始终从同一库调用该方法的已知实现。this 其他库无法重写接口的方法 类自己的方法以后可能会以意想不到的方式调用。 这减少了脆弱的基类问题。

// Library a.dart
interface class Vehicle {
  void moveForward(int meters) {
    // ...
  }
}
// Library b.dart
import 'a.dart';

// Can be constructed
Vehicle myVehicle = Vehicle();

// ERROR: Cannot be inherited
class Car extends Vehicle {
  int passengers = 4;
  // ...
}

// Can be implemented
class MockVehicle implements Vehicle {
  @override
  void moveForward(int meters) {
    // ...
  }
}

abstract interface

修饰符最常见的用途是定义纯接口。组合 和 abstract 修饰符。interfaceinterfaceabstract interface class

像类一样,其他库可以实现,但不能继承, 一个纯粹的界面。像类一样,纯接口可以有 抽象成员。interfaceabstract

final

若要关闭类型层次结构,请使用修饰符。 这样可以防止从当前库之外的类进行子类型化。 不允许继承和实现会完全阻止子类型化。 这保证了:final

  • 您可以安全地向 API 添加增量更改。
  • 您可以调用实例方法,因为它们尚未在 第三方子类。

最终类可以在 同一个库。修饰符包含 和 的效果 因此,任何子类也必须标记为 、 或 。finalbasebasefinalsealed

// Library a.dart
final class Vehicle {
  void moveForward(int meters) {
    // ...
  }
}
// Library b.dart
import 'a.dart';

// Can be constructed
Vehicle myVehicle = Vehicle();

// ERROR: Cannot be inherited
class Car extends Vehicle {
  int passengers = 4;
  // ...
}

class MockVehicle implements Vehicle {
  // ERROR: Cannot be implemented
  @override
  void moveForward(int meters) {
    // ...
  }
}

sealed

若要创建一组已知的、可枚举的子类型,请使用修饰符。 这允许您创建静态确保的子类型的切换 详尽无遗。sealed

修饰符阻止扩展类或 在自己的库之外实现。密封类是隐式抽象的。sealed

  • 它们不能自己建造。
  • 它们可以有工厂构造函数。
  • 它们可以定义构造函数供其子类使用。

然而,密封类的子类并不是隐含的抽象。

编译器知道任何可能的直接子类型 因为它们只能存在于同一个库中。 这允许编译器在开关不 详尽地处理所有可能的亚型:

sealed class Vehicle {}

class Car extends Vehicle {}

class Truck implements Vehicle {}

class Bicycle extends Vehicle {}

// ERROR: Cannot be instantiated
Vehicle myVehicle = Vehicle();

// Subclasses can be instantiated
Vehicle myCar = Car();

String getVehicleSound(Vehicle vehicle) {
  // ERROR: The switch is missing the Bicycle subtype or a default case.
  return switch (vehicle) {
    Car() => 'vroom',
    Truck() => 'VROOOOMM',
  };
}

如果您不想进行详尽的切换, 或者希望以后能够在不破坏 API 的情况下添加子类型, 使用 final 修饰符。为了进行更深入的比较, 阅读密封版与最终版。

组合修饰符

您可以组合一些修饰符以实现分层限制。 类声明可以按顺序:

  1. (可选) ,描述类是否可以包含抽象成员 并防止实例化。abstract
  2. (可选)、 或 之一,描述 对子类型化类的其他库的限制。baseinterfacefinalsealed
  3. (可选),描述声明是否可以混入。mixin
  4. 关键字本身。class

您不能组合某些修饰符,因为它们是矛盾的、多余的或 否则互斥:

  • abstract跟。密封类始终是隐式抽象的。sealed
  • interface或 .这些访问修饰符 防止混入。finalsealedmixin 有关完整指导,请参阅类修饰符参考。

Comments

Make a comment