DartのMixinsの紹介
オブジェクト指向プログラミング(OOP)を使用する最も良い理由のいくつかは、コードをクリーンでドライに保つのに役立つテクニックです。 コードを別々のクラスで再利用できるようにするためのDartの戦略のいくつかを探求します。
問題
2つのクリーチャークラスがあり、それぞれが独自の動作セットを持っていると想像してください。 明らかな解決策は、必要に応じて各クラスのメソッドの概要を直接示すことですが、多くのクラスは完全に一意ではなく、互いに多くの共通点を共有します。 これらのクラスを最も再利用可能な方法で作成するための最も効率的な構造を見つけたいのは明らかです。
私たちの動物は、実行できるいくつかの特定のアクションと、それらから構成されるより大きな行動を持ちます。 ご覧のとおり、食事は異なる場合がありますが、方法はほとんど同じであり、理想的にはより再利用可能なものに分割する必要があります。
class Alligator {
void swim() => print('Swimming');
void bite() => print('Chomp');
void crawl() => print('Crawling');
void hunt() {
print('Alligator -------');
swim();
crawl();
bite();
print('Eat Fish');
}
}
class Crocodile {
void swim() => print('Swimming');
void bite() => print('Chomp');
void crawl() => print('Crawling');
void hunt() {
print('Crocodile -------');
swim();
crawl();
bite();
print('Eat Zebra');
}
}
main() {
Crocodile().hunt();
Alligator().hunt();
}
// Output should be
// Crocodile -------
// Swimming
// Crawling
// Chomp
// Eat Zebra
// Alligator -------
// Swimming
// Crawling
// Chomp
// Eat Fish
拡張機能
私たちが持っている最も一般的なオプションは拡張機能です。この拡張機能では、あるクラスのプロパティとメソッドを取得して、別のクラスで使用できるようにすることができます。 Reptile
を独自のインスタンスで使用しないため、抽象クラスとして設定して、初期化できず、拡張するだけで済みます。
abstract class Reptile {
void bite() => print('Chomp');
void swim() => print('Swimming');
void crawl() => print('Crawling');
void hunt() {
print('${this.runtimeType} -------');
swim();
crawl();
bite();
}
}
class Alligator extends Reptile {
// Alligator Specific stuff...
}
class Crocodile extends Reptile {
// Crocodile Specific stuff...
}
main() {
Crocodile().hunt('Zebra');
Alligator().hunt('Fish');
}
Mixins
これは現在の例では良いことですが、動物を追加すると、これらの方法の多くが爬虫類だけのものではないことがすぐに明らかになります。 Reptile
を拡張するだけでなく、swimメソッドを使用してFish
クラスを作成したい場合は、extends
クラスごとに1つ。 ミックスインを使用して、より普遍的な動作をより小さく、より再利用可能なコンポーネントに分割し、必要なクラスに追加することができます。
メソッドを格納するためにmixin
タイプを使用し、それを含めるすべてのクラスでwith
キーワードを使用する必要があります。 extendsとは異なり、クラスに必要な数のミックスインを追加できます。
mixin Swim {
void swim() => print('Swimming');
}
mixin Bite {
void bite() => print('Chomp');
}
mixin Crawl {
void crawl() => print('Crawling');
}
abstract class Reptile with Swim, Crawl, Bite {
void hunt(food) {
print('${this.runtimeType} -------');
swim();
crawl();
bite();
print('Eat $food');
}
}
class Alligator extends Reptile {
// Alligator Specific stuff...
}
class Crocodile extends Reptile {
// Crocodile Specific stuff...
}
class Fish with Swim, Bite {
void feed() {
print('Fish --------');
swim();
bite();
}
}
main() {
Crocodile().hunt('Zebra');
Alligator().hunt('Fish');
Fish().feed();
}
の上
私たちが持っている最後のトリックは、私が逆拡張として考えたいことをする能力です。 クラスのメソッドを利用するミックスインを作成し、それを各サブクラスで使用できます。
Hunt
を独自のミックスインに分割したい場合は、on
キーワードを使用して、Reptile
クラスでのみ使用されることを通知できます。 Swim
、Crawl
、Bite
ミックスインなどのすべての機能にアクセスできます。
この構成は、最初の構成とまったく同じ出力になるはずです。
mixin Hunt on Reptile {
void hunt(food) {
print('${this.runtimeType} -------');
swim();
crawl();
bite();
print('Eat $food');
}
}
abstract class Reptile with Swim, Crawl, Bite {}
class Alligator extends Reptile with Hunt {
// Alligator Specific stuff...
}
class Crocodile extends Reptile with Hunt {
// Crocodile Specific stuff...
}
結論
Flutterの人気が高まるにつれ、Dartプログラミング言語の基本を十分に理解することをお勧めします。 うまくいけば、これがDartクラスの再利用に関する謎のいくつかを明らかにするための有益な紹介でした。