刚开始学习 Dart ,这是其中一篇笔记。
mixin 是在多重继承中,复用某个类中代码的方法模式。
比如 A、B、C 三个音乐家,A 会弹钢琴和弹吉他,B 会弹钢琴和玩乌克丽丽,C 会玩乌克丽丽和弹吉他。 我们可以定义这样三个类。
class Musician {
}
abstract class Paino {
void playPaino();
}
abstract class Guita {
void playGuita();
}
abstract class Ukelele {
void playUkelele();
}
class A extends Musician implements Paino, Guita {
void playPaino() {}
void playGuita() {}
}
class B extends Musician implements Paino, Ukelele {
void playPaino() {}
void playUkelele() {}
}
class C extends Musician implements Ukelele, Guita {
void playUkelele() {}
void playGuita() {}
}
以上方法可以解决我们的问题,但是又有一个新的问题出来了:
我们将要在每个类中都实现 void playPaino() 、void playGuita() 和 void playUkelele() 方法。
这样做可能太过麻烦,而且也不符合 DRY 的原则。
有什么其他办法可以将相同的方法抽取出来呢?
这时候 mixin 就登场了。
使用 mixin 关键字来完成上面的需求。
class Musician {
}
mixin GuitaMaster {
void playGuita() {
print('guita master');
}
}
mixin PainoMaster {
void playPaino() {
print('paino master');
}
}
mixin UkeleleMaster {
void playUkelele() {
print('ukelele master');
}
}
mixin PokemonMaster {
void playPokemonGo() {
print('pokemon get daze!');
}
}
class A with GuitaMaster, PainoMaster {
}
class B with PainoMaster, UkeleleMaster {
}
class C with UkeleleMaster, GuitaMaster {
}
注意区别:在 abstract 中我们并没有定义接口的实现逻辑,只是规定实现类中必须实现该方法。
在
abstract类中,我们可以实现具体的方法,但当abstract类被当作接口来使用时,必须在类中重新实现该方法,而忽略了抽象内中的实现。abstract类可以被当作父类使用,所以使用extends拓展子类时,抽象内的实现可以被执行。
但是在 mixin 中,我们定义了具体的方法实现。
这样依旧解决我们的需求,而且复用性更强。
此外像上面那样定义 mixin,其实 class 本身也可以被当作 mixin。
另外需要注意的是:
mixin 必须是直接继承 Object 类的,或者是直接或者间接继承 extends 关键字后面的类。
可以指定 on 关键字,指定哪些类可以被继承。
下面的例子中,只有当被混入的子类拓展于 Musician 类时,才会生效。
class Musician {
}
class Pokemonor {
}
mixin GuitaMaster on Musician {
void playGuita() {
print('guita master');
}
}
mixin PainoMaster on Musician {
void playPaino() {
print('paino master');
}
}
mixin UkeleleMaster on Musician {
void playUkelele() {
print('ukelele master');
}
}
mixin PokemonMaster on Pokemonor {
void playPokemonGo() {
print('pokemon get daze!');
}
}
class A extends Musician with GuitaMaster, PainoMaster {
}
class B extends Musician with PainoMaster, UkeleleMaster {
}
class C extends Musician with UkeleleMaster, GuitaMaster {
}
// 下面这个例子会报错,因为它不继承于 `Musician` 类
class D extends Pokemonor with UkeleleMaster {
}