最近お気に入りのresocoderさんの、mixinに関する記事で学習しました。
Mixinが必要になるストーリー
単一継承でうまくいっているパターン
-
Mosquitoクラスが抽象クラスAirborneInsectを継承(extends)します。 -
AirborneInsectクラスはflutter()、buzz()というメソッドを持っています。 -
Mosquitoクラスのインスタンスはflutter()呼び出せます!
単一継承でうまくいかないパターン
- 昆虫だけでなく、鳥も扱うことになりました!
- 抽象クラス
Birdでflutter()を持ちます。 -
Birdを継承したSwallowでflutter()を呼び出せます! - しかしこの
flutter()はAirborneInsectとBirdで重複しています!
複数の抽象クラスが同じメソッドを持つ重複を解決: mixin
ここで多重継承を可能にするmixinを使います。
以下のコードではFlutteringクラスを、AirborneInsectとBird適用しています。
これでコードの重複がなくなりました!
実際のコード
mixin Fluttering {
void flutter() {
print('fluttering');
}
}
abstract class Insect {
void crawl() {
print('crawling');
}
}
abstract class AirborneInsect extends Insect with Fluttering {
void buzz() {
print('buzzing annoyingly');
}
}
class Mosquito extends AirborneInsect {
void doMosquitoThing() {
crawl();
flutter();
buzz();
print('sucking blood');
}
}
abstract class Bird with Fluttering {
void chirp() {
print('chirp chirp');
}
}
class Swallow extends Bird {
void doSwallowThing() {
chirp();
flutter();
print('eating a mosquito');
}
}
Mixinの使い方
mixinで定義して、with句で適用します。
fieldとmethodを継承できます。また、複数mixinを適用できます。
またmixinは親クラスに適用され、新しい匿名クラスを生成しているようです。
// mixinの定義
mixin M1{
int number = 42;
void say() => print('M1!');
}
mixin M2{
String name = 'M2';
void hello() => print('hello!');
}
// mixinの適用
class C extends Object with M1, M2 {}
main() {
var c = C();
c.say(); // M1!
c.hello(); // hello!
print(c.number); // 42
print(c.name); // M2
}
まずはコードの重複をなくす目的で使ってみると良いと思います。