Flutter/Dart第20天:Dart 3.0新特性之类型修饰符
Dart官方文档:https://dart.dev/language/class-modifiers
重要说明:本博客依据Dart官网文档,但并不是简略的对官网进行翻译,在掩盖中心功用状况下,我会依据个人研制经历,参加自己的一些扩展问题和场景验证。
类型润饰符主要是操控类或许Mixin怎么被运用,包括在库内部和外部运用。润饰符关键字出现在类型或Mixin声明的前面,如abstract class
经过abstract
润饰符界说了一个笼统类。
可用于声明类的润饰符关键字列表如下:
- abstract
- base
- final
- interface
- sealed
- mixin
束缚:上面的润饰符列表,只要base
能用于Mixin类型;一起,上诉润饰符不能用于包括enum
、typedef
和extension
等类型声明。
实战:当咱们决议要运用润饰符时,或许需求考虑一下类的预期用处和类需求供给哪些行为。
无润饰符
当咱们界说类或许Mixin时,不期望对结构函数或许子类进行束缚时,咱们能够不运用润饰符。
当类或许Mixin没有润饰符时,默许状况下,能够对这些类或许Mixin进行以下操作:
- 经过结构函数创立类实例
- 经过承继类来创立子类
- 完成类或许Mixin的接口
- 混入Mixin或许Mixin类
abstract润饰符(笼统类)
运用场景:当咱们界说了一个类(即:笼统类),但又没有完好地完成了它一切的接口时运用(和Java言语相同),请运用abstract
润饰符。
束缚:笼统类不能被实例化;一般状况,笼统类都包括笼统办法。
// 笼统类
abstract class Vehicle {
void moveForward(int meters);
}
// 完成类
class MockVehicle implements Vehicle {
@override
void moveForward(int meters) {
// ...
}
}
base润饰符(基类)
运用场景:当咱们用base
润饰符界说了一个类或许Mixin时(即:基类),那么这个基类的完成只能基类地点库内。这样做的意图:
- 每逢创立子类实例时,基类的结构函数被调用
- 一切现已完成的私有成员都在子类中
- 在基类中新添加的成员会被一切子类承继(除非:子类中声明晰同名的成员但并不兼容的签名。如:子类声明晰同名办法,可是办法入参或许回来结果与基类不兼容)
实战:为了确保基类不会被损坏,子类有必要运用base
,final
或许sealed
润饰符。
如下代码样例,基类能够实例化、被承继,可是不能被完成:
// 基类
base class Vehicle {
void moveForward(int meters) {
// ...
}
}
// 1. 实例化
Vehicle myVehicle = Vehicle();
// 2. 被承继
base class Car extends Vehicle {
int passengers = 4;
// ...
}
// 3. ERROR:不能被完成
base class MockVehicle implements Vehicle {
@override
void moveForward() {
// ...
}
}
interface润饰符(接口类)
运用场景:运用interface
润饰符界说一个接口。接口能够被外部库完成,可是不能被承继。这样做的意图:
- 当类的一个实例办法运用
this
调用另一个实例办法时,它总是调用同一个库的实例办法 - 为了防止不行预期的办法调用,其他库不能从头接口已有的办法
如下代码样例,接口类能够实例化、被完成,可是不能被承继:
// a.dart 接口类
interface class Vehicle {
void moveForward(int meters) {
// ...
}
}
//
// b.dart
//
import 'a.dart';
// 1. 实例化
Vehicle myVehicle = Vehicle();
// 2. 被完成
class MockVehicle implements Vehicle {
@override
void moveForward(int meters) {
// ...
}
}
// 3. ERROR: 不能被承继
class Car extends Vehicle {
int passengers = 4;
// ...
}
abstrace interface(笼统接口类)
一般状况下,咱们运用interface
来界说朴实接口。
当咱们运用abstract interface class
组合润饰符时,能够界说一个笼统接口类:它即有接口类的功用(可被完成,但不能被承继),也有笼统类的功用(有笼统成员)。
final润饰符(不行变类)
运用场景:当运用final
润饰符时,表明该类不能被其他库承继和完成(和Java还有点不相同)。这样做的意图:
- 能够安全地进行API改变
- 该类不会被第三方子类掩盖,因而能够定心调用实例办法
束缚:final
不行变类能够在本库中被承继和完成,final
润饰符包括了base
润饰符特性,因而,子类有必要运用base
,final
或许sealed
润饰符。
// a.dart 接口类
final class Vehicle {
void moveForward(int meters) {
// ...
}
}
//
// b.dart
//
import 'a.dart';
// 1. 实例化
Vehicle myVehicle = Vehicle();
// 2. ERROR: 不能被承继
class Car extends Vehicle {
int passengers = 4;
// ...
}
class MockVehicle implements Vehicle {
// 3. ERROR: 不能被完成
@override
void moveForward(int meters) {
// ...
}
}
sealed润饰符(密封类)
运用场景:当咱们界说了一个类(即:密封类),且清晰该类的一切子类集合时,请运用sealed
润饰符。这答应咱们经过switch
穷举一切的子类型。
束缚:sealed
润饰的类,制止被其他库承继或许完成,它隐含abstract
润饰符:
- 不能被实例化
- 能够有工厂结构函数
- 能够界说结构函数,子类可直接运用
- 子类并不是
abstract
笼统类
编译器能够知道一切sealed
润饰符类的子类(由于他们在同一个库中),这样在switch
中,如未穷举,编译器能宣布过错正告!
// 密封类
sealed class Vehicle {}
class Car extends Vehicle {}
class Truck implements Vehicle {}
class Bicycle extends Vehicle {}
// 1. ERROR: 不能被实例化
Vehicle myVehicle = Vehicle();
// 2. 子类能够被实例化
Vehicle myCar = Car();
String getVehicleSound(Vehicle vehicle) {
// 3. ERROR: switch中子类未穷举(还有Bicycle子类)
return switch (vehicle) {
Car() => 'vroom',
Truck() => 'VROOOOMM',
};
}
在switch
中,假如咱们不想穷举sealed
类的子类;又或许今后还会添加子类,但又不想损坏API规划,我也能够运用final
润饰符。关于final
和sealed
润饰符的深化比较,请稍等本博客的下一个博客介绍(请容许我卖个关子!)。
组合润饰符
经过组合润饰符,能够起到叠加束缚作用。咱们声明类时,依照次序,能够叠加的润饰符:
- 可选的
abstract
润饰符:类包括笼统成员,且不能被实例化 - 可选的
base
、interface
、final
和sealed
润饰符:束缚其他库的子类型 - 可选的
mixin
润饰符:类是否可被混入 - 必选的
class
类关键字
部分润饰符是不能组合运用,由于他们或许剩余或许对立互斥:
abstract
润饰符和sealed
润饰符:原因是sealed
隐含了abstract
润饰符interface
、final
或sealed
润饰符和mixin
润饰符:原因是这些润饰符都制止被混入
完好的有用的润饰符组合列表如下:
我的本博客原地址:https://ntopic.cn/p/2023110501