theme: cyanosis
在 dart 3.0.0 之后,对类型的修饰符进行了拓展,现在类型的修饰符有:
| 名称 | 作用 | | --- | --- | | mixin | 混入类修饰符 | | sealed | 密封可枚举的子类型 | | abstract | 抽象类修饰符 | | final | 一定程度上关闭派生能力 | | base | 基 | | interface | 接口 |
1. mixin 语法变化
在 dart 3.0.0 之前, 没有构造方法的 class 可以视为 mixin , 下面的代码是允许的:
``` class A {}
class C with A {} ```
在 dart 3.0.0 之后, mixin 变严格了,和 class 声明的常规类进行的区分,常规类将不被允许混入:
想要通过 with 关键字混入 A,需要通过 mixin 声明类:
``` mixin A {}
class C with A {} ```
或者通过 mixin 关键字对 class 进行修饰:
``` mixin class A {}
class C with A {} ```
也就是说,现在 Dart 中将 混入类 和 常规类 进行了语法级别的区分:
mixin 声明定义了一个混入类,允许被通过 with 混入或 on 继承。
class 声明定义了一个常规类,允许被通过 extends 继承。
mixin class 声明定义了一个既可用作常规类又可用作混入类的类。即允许被通过 with 混入或 on 继承,又允许被通过 extends 继承。
- 在新语法中只有
常规类
才允许使用extends
或with
子句,混入类不允许使用; - 只有
混入类
才允许使用on
子句,常规类不允许使用。 - 而
mixin class
含有两者的血脉,所以即无法使用extends
或with
子句,也无法使用on
子句。
2. 密封类的支持 sealed
有些类型的子类型集是已知的,可枚举的;比如登陆界面的认证状态 AuthState
,有如下三种子状态
- 认证中 AuthLoading
- 认证成功 AuthSuccess
- 认证失败 AuthFailure
这时就可以通过密封类来处理,下面的代码看起来似乎和平台的继承也没什么区别,但密封类有它的特点。
``` sealed class AuthState{} //创建密封类
class AuthLoading extends AuthState{}
class AuthSuccess extends AuthState{ final String user; final String token;
AuthSuccess(this.user, this.token); }
class AuthFailure extends AuthState{ final String error; AuthFailure(this.error); } ```
- sealed 修饰的类自动是抽象类,无法被实例化。
- sealed 修饰的类无法在外部被 继承 extended, 实现 implemented, 或 混入 with。
- sealed 修饰的类可以被 switch 选择。
如下所示,根据AuthState
的不同状态,返回不同的字符串。在实际开发中可以返回不同的组件,在对应的分支中可以访问对应派生类中的字段。比如 AuthSuccess 分支中可以通过state.user
访问用户名;AuthFailure 分支中可以通过state.error
访问错误信息:
String buildByAuthState(AuthState state){ return switch(state){ AuthLoading()=> 'AuthLoading View', AuthSuccess()=> 'AuthSuccess View:${state.user}', AuthFailure()=> 'AuthFailure View:${state.error}', }; }
sealed 最大的特点是子类型可枚举,所以在编码过程中如果少写一个,编译器就是显示地给出提示。这样可以有效避免漏写的可能,这种从语法层面规避潜藏风险,对代码的健壮性是非常友好的。
3. final 类型修饰符
final 对类进行修饰,其目的是为了关闭该类的继承体系。如下所示,被 final 修饰的类无法被直接继承;
从提示中可以看出需要继承自 final 修饰的类,子类需要被 base 、final 或 sealed 修饰:
另外 final 修饰的类无法在外部进行派生:
从这两点就不难理解,final 修饰的类可以在一定程度上关闭派生能力。
4. base 和 interface 类修饰符
base 和 interface 在我看来是一对,base 是强调 继承
; interface 是强调 实现
。两者的的目的是:
限制外部文件对修饰类的派生和实现。
base 修饰的类在外部 允许继承,不允许实现
interface 修饰的类在外部 不允许继承,允许实现
俗话说无规矩不成方圆,修饰符就是限制的规则,而接受限制就会享有更长远的利益。比如接受红绿灯的限制,会让整体的交通更加顺畅,减少拥堵,出事的可能性。而不是纠结于我多等了几十秒,不利于一时的享受。限制这是一种大局观,其目的是让整体更加有序。
类型修饰符的增加,可以让类本身多了一些特点,也可以控制类的派生能力,这对于构建大型应用来说是友好的。Kotlin 一直都有 sealed 密封类,这是让我垂涎的语法特性,现在 Dart 终于支持了。