Mixins 就像是可插拔的功能模块,可以给多个不同的类批量添加相同的功能实现,而不需要这些类有共同的父类。
要使用mixin功能,请使用with关键字,后跟一个或多个mixin名称。下面的例子展示了两个使用mixins的类(或者它们是mixins的子类):
dart
class Musician extends Performer with Musical {
// ···
}
class Maestro extends Person with Musical, Aggressive, Demented {
Maestro(String maestroName) {
name = maestroName;
canConduct = true;
}
}
要定义一个mixin,使用mixin声明。在需要同时定义mixin和类的罕见情况下,可以使用mixin类声明。
mixin和mixin类不能有extends子句,并且不能声明任何生成构造函数。
声明案例如下:
dart
mixin Musical {
bool canPlayPiano = false;
bool canCompose = false;
bool canConduct = false;
void entertainMe() {
if (canPlayPiano) {
print('Playing piano');
} else if (canConduct) {
print('Waving hands');
} else {
print('Humming to self');
}
}
}
Specify members a mixin can call on itself
指定mixin可以调用自身的成员
有时,mixin依赖于能够调用方法或访问字段,但不能自己定义这些成员(因为mixin不能使用构造函数的参数来实例化自己的字段)。
下面几节将介绍确保mixin的任何子类定义mixin行为所依赖的任何成员的不同策略。
Define abstract members in the mixin
在mixin中声明抽象方法会强制任何使用mixin的类型定义其行为所依赖的抽象方法。
dart
mixin Musician {
void playInstrument(String instrumentName); // Abstract method.
void playPiano() {
playInstrument('Piano');
}
void playFlute() {
playInstrument('Flute');
}
}
class Virtuoso with Musician {
@override
void playInstrument(String instrumentName) { // Subclass must define.
print('Plays the $instrumentName beautifully');
}
}
Mixin 可以定义抽象成员,访问子类的状态
下面的例子可以应用于任何带有[name]属性的类型,并提供实现了[hashCode]和运算符' == '。
dart
mixin NameIdentity {
String get name;
@override
int get hashCode => name.hashCode;
@override
bool operator ==(other) => other is NameIdentity && name == other.name;
}
class Person with NameIdentity {
final String name;
Person(this.name);
}
Implement an interface
与声明mixin抽象类似,在不实际实现接口的同时在mixin上放置一个实现子句也将确保为mixin定义任何成员依赖项。
dart
abstract interface class Tuner {
void tuneInstrument();
}
mixin Guitarist implements Tuner {
void playSong() {
tuneInstrument();
print('Strums guitar majestically.');
}
}
class PunkRocker with Guitarist {
@override
void tuneInstrument() {
print("Don't bother, being out of tune is punk rock.");
}
}
Use the on clause to declare a superclass
on 子句的作用是定义 super 调用所解析的类型。因此,只有当你在 mixin 中需要进行 super 调用时才应该使用它。
on 子句强制任何使用该 mixin 的类也必须是 on 子句中类型的子类。这确保了如果 mixin 依赖于超类中的成员,那么在使用 mixin 的地方这些成员是可用的。
如果M是个mixin同时on了A,如果你想在B类中混入M,那么B必须是A的子类。
dart
class Musician {
musicianMethod() {
print('Playing music!');
}
}
mixin MusicalPerformer on Musician {
performerMethod() {
print('Performing music!');
super.musicianMethod();
}
}
class SingerDancer extends Musician with MusicalPerformer { }
main() {
SingerDancer().performerMethod();
}
class, mixin, or mixin class?
mixin class声明需要至少3.0的语言版本。
Mixin 声明定义一个 mixin。class声明定义一个类。Mixin class声明定义一个既可以作为普通类使用,又可以作为 mixin 使用的类,具有相同的名称和相同的类型。
dart
mixin class Musician {
// ...
}
class Novice with Musician { // Use Musician as a mixin
// ...
}
class Novice extends Musician { // Use Musician as a class
// ...
}
适用于类或 Mixin 的任何限制也适用于 Mixin 类:
Mixin 不能有 extends 或 with 子句,所以 Mixin 类也不能有。
类不能有 on 子句,所以 Mixin 类也不能有。