类修饰符控制一个类或 mixin
如何被使用,无论是在其自身的库内部,还是在定义它的库的外部。
修饰符关键字位于类或 mixin
声明之前。例如,abstract class
定义了一个抽象类。可以出现在类声明之前的完整修饰符集合包括:
- abstract
- base
- final
- interface
- sealed
- mixin
只有 base
修饰符可以出现在 mixin
声明之前。修饰符不适用于其他声明,如 enum
、typedef
或 extension
。
在决定是否使用类修饰符时,考虑类的预期用途,以及类需要依赖的行为。
无修饰符
要允许任何库无限制地构造或子类型化,使用没有修饰符的类或 mixin
声明。默认情况下,你可以:
- 构造类的新实例。
- 扩展类以创建新的子类型。
- 实现类或
mixin
的接口。 - 混入
mixin
或mixin
类。
abstract
要定义一个不需要其全部接口的完全、具体实现的类,使用 abstract
修饰符。
- 抽象类不能从任何库(无论是自己的还是外部的库)构造。抽象类通常有抽象方法。
- 如果你希望你的抽象类看起来可以实例化,定义一个工厂构造函数。
base
要强制继承类或 mixin
的实现,使用 base
修饰符。基类禁止在其自身的库之外实现。这保证了:
- 每当创建一个类的子类型的实例时,都会调用基类的构造函数。
- 所有实现的私有成员都存在于子类型中。
- 在基类中新增的成员不会破坏子类型,因为所有子类型都继承了新的成员。
你必须将实现或扩展基类的任何类标记为 base
、final
或 sealed
。这防止外部库破坏基类的保证。
interface
要定义一个接口,使用 interface
修饰符。定义接口的库外部的库可以实现接口,但不能扩展它。这保证了:
- 当类的实例方法调用另一个实例方法时,它总是会调用来自同一个库的已知实现。
abstract interface
interface
修饰符最常用来定义纯接口。将 interface
和 abstract
修饰符组合起来,定义一个抽象接口类。
- 像接口类一样,其他库可以实现,但不能继承纯接口。像抽象类一样,纯接口可以有抽象成员。
final
要关闭类型层次结构,使用 final
修饰符。这防止从当前库外部的类进行子类型化。禁止继承和实现防止完全子类型化。这保证了:
- 你可以安全地向API添加增量更改。
- 你可以调用实例方法,知道它们在第三方子类中没有被覆盖。
final
类可以在同一库内被扩展或实现。final
修饰符包含 base
的效果,因此任何子类也必须标记为 base
、final
或 sealed
。
sealed
要创建一个已知的、可枚举的子类型集合,使用 sealed
修饰符。这允许你创建一个在静态上确保是详尽无遗的那些子类型上的 switch
。
sealed
修饰符防止一个类在其自身的库之外被扩展或实现。sealed
类隐含地是抽象的。
- 它们不能被自身构造。
- 它们可以有工厂构造函数。
- 它们可以为其子类定义构造函数。
然而,sealed
类的子类并不隐含地是抽象的。
编译器知道任何可能的直接子类型,因为它们只能在同一个库中存在。这允许编译器在 switch
没有详尽地处理所有可能的子类型时提醒你:
如果你不希望进行详尽的切换,或者希望能够在后续添加子类型而不破坏API,使用 final
修饰符。
组合修饰符
你可以组合一些修饰符进行分层限制。一个类声明可以按照以下顺序:
- (可选)
abstract
,描述类是否可以包含抽象成员并阻止实例化。 - (可选)
base
、interface
、final
或sealed
中的一个,描述对其他库子类型化类的限制。 - (可选)
mixin
,描述声明是否可以被混入。 - 类关键字本身。
你不能组合一些修饰符,因为它们是矛盾的、冗余的,或者相互排斥的:
abstract
与sealed
。一个sealed
类总是隐含地是抽象的。interface
、final
或sealed
与mixin
。这些访问修饰符阻止混入。