Dart中类的类型
Dart
是支持基于mixin
继承机制的面向对象语言,所有对象都是一个类的实例,而除了 Null
以外的所有的类都继承自Object
类。 基于mixin
的继承意味着尽管每个类(top class Object? 除外)都只有一个超类,一个类的代码可以在其它多个类继承中重复使用。
以上这段是官方文档的说明,在实际使用中,由于mixin
的加入,使得Dart
中类的使用和其它语言有所不同。Dart中类的类型有三种,分别是:
class
:声明一个类,提供具体的成员变量和方法实现。abstract class
:声明一个抽象类,抽象类将无法被实例化。抽象类常用于声明接口方法、有时也会有具体的方法实现。mixin
:声明一个Mixin
类,与抽象类一样无法被实例化,是一种在多重继承中复用某个类中代码的方法模式,可以声明接口方法或有具体的方法实现。
- 每一个类都隐式地定义了一个接口并实现了该接口,这个接口包含所有这个类的成员变量以及这个类所实现的其它接口。
- 如果想让抽象类同时可被实例化,可以为其定义
工厂构造函数
。具体内容可以参考:抽象类的实例化mixin
关键字在Dart 2.1
中才被引用支持。早期版本中的代码通常使用abstract class
代替
从上述内容可以看出,mixin
是后面才被引入的,与abstract class
有些通用的地方,可以理解为abstract class
的升级版。它相对于abstract class
说,可以同时引入多个Mixin
,并且可以通过on
关键字来限制使用范围。
类相关关键字的使用
而对上述这些类型的使用,又有extends
, with
, implements
, on
这几个关键字:
extends
:继承,和其它语言的继承没什么区别。with
:使用Mixin
模式混入一个或者多个Mixin类
。implements
:实现一个或多个接口并实现每个接口定义的API。on
:限制Mixin
的使用范围。
针对这几个关键字的使用,我做了一张表进行总结:
样例说明
针对上面的内容,我举几个例子,可以复制代码到DartPad中进行验证:
类混入类或者抽象类(class with class)
1 | class Animal { |
类继承抽象类并混入Mixin
1 | class Animal { |
类继承抽象类并混入Mixin的同时实现接口
1 | class Biology { |
混入mixin的顺序问题
1 | abstract class Biology { |
这里的顺序问题和运行出来的结果会让人有点费解,但是可以这样理解:Mixin
语法糖, 本质还是类继承. 继承可以复用代码, 但多继承会导致代码混乱。 Java
为了解决多继承的问题, 用了interface
, 只有函数声明而没有实现(后面加的default
也算语法糖了)。以A with B, C, D
为例,实际是A extends D extends C extends B
, 所以上面的Animal
必须在Flyer
前面,否则就变成了Animal extends Flyer
,会出现儿子给爹当爹的混乱问题。
mixin的底层本质只是猜测,并没有查看语言底层源码进行验证.
总结
从上述样例可以看出,三种类结构可以同时存在,关键字的使用有前后顺序:extends -> mixins -> implements
。
另外需要注意的是相同方法的优先级问题,这个有两种情况:
- 同时被
extends
,with
,implements
时,混入(with
)的优先级比继承(extends
)要高,而implements
只提供接口,不会被调用。 with
多个Mixin
时,则会调用距离with
关键字最远Mixin
中的方法。
当然,如果当前使用类重写了该方法,就会优先调用当前类中的方法。
参考资料
- Dart官方文档
- Dart之Mixin详解
- Flutter 基础 | Dart 语法 mixin:对
mixin
的使用场景进行了很好的说明