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)
class Animal {
String name = "Animal";
}
abstract class Flyer {
String name = "Flyer";
void fly() => print('$name can fly!');
}
abstract class Eater extends Animal {
void eat() => print('I can Eat!');
}
// 一起混入class和abstract class
abstract class Bird with Animal, Flyer {}
class Bird1 with Animal, Flyer {}
// 只支撑无任何承继和混入的类,Eater承继自Animal,所以它不支撑被混入。
// 报错:The class 'Eater' can't be used as a mixin because it extends a class other than 'Object'.
// class Bird with Eater {
// }
main() {
Bird1().fly(); // Flyer can fly!
}
类承继抽象类并混入Mixin
class Animal {
String name = "Animal";
}
mixin Flyer {
String name = "Flyer";
void fly() => print('$name can fly!');
}
abstract class Eater extends Animal {
@override
String get name => "Eater";
void eat() => print('$name can Eat!');
}
// 类承继抽象类并混入Mixin
class Bird extends Eater with Flyer { }
main() {
// 由于with(混入)的优先级比extends(承继)更高,所以打印出来的是Flyer而不是Eater
Bird().fly(); // Flyer can fly!
Bird().eat(); // Flyer can Eat!
}
类承继抽象类并混入Mixin的一起完成接口
class Biology {
void breathe() => print('I can breathe');
}
class Animal {
String name = "Animal";
}
// 这儿设置完成了Biology接口,可是mixin与abstract class相同并不要求完成接口,声明与完成均可。
// on关键字约束混入Flyer的类必须承继自Animal或它的子类
mixin Flyer on Animal implements Biology {
@override
String get name => "Flyer";
void fly() => print('$name can fly!');
}
abstract class Eater extends Animal {
@override
String get name => "Eater";
void eat() => print('$name can Eat!');
}
// 类承继抽象类并混入Mixin的一起完成接口
// 留意关键字的运用次序,依次是extends -> with -> implements
class Bird extends Eater with Flyer implements Biology {
// 后边运用了`implements Biology`,所以子类必需求完成这个类的接口
@override
void breathe() => print('Bird can breathe!');
}
main() {
// 由于with(混入)的优先级比extends(承继)更高,所以打印出来的是Flyer而不是Eater
Bird().fly(); // Flyer can fly!
Bird().eat(); // Flyer can Eat!
Bird().breathe(); // Bird can breathe!
}
混入mixin的次序问题
abstract class Biology {
void breathe() => print('I can breathe');
}
mixin Animal on Biology {
String name = "Animal";
@override
void breathe() {
print('$name can breathe!');
super.breathe();
}
}
mixin Flyer on Animal {
@override
String get name => "Flyer";
void fly() => print('$name can fly!');
}
/// mixin的次序问题:
/// with后边的Flyer必须在Animal后边,不然会报错:
/// 'Flyer' can't be mixed onto 'Biology' because 'Biology' doesn't implement 'Animal'.
class Bird extends Biology with Animal, Flyer {
@override
void breathe() {
print('Bird can breathe!');
super.breathe();
}
}
main() {
Bird().breathe();
/*
* 上述代码履行,依次输出:
* Bird can breathe!
* Flyer can breathe!
* I can breathe
* */
}
这儿的次序问题和运行出来的成果会让人有点费解,可是能够这样了解: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
的运用场景进行了很好的说明
by: 星的天空