[Flutter] - Mixin


Dart 언어는 기본적으로 단일 상속만을 지원한다.

만약 다중 상속이 필요하다면 어떻게 해야할까?

그 문제를 해결하고자 Mixin을 공부하게 되었다.

이미지

기존에는 위와 같이 상속을 통하여 객체를 만들어 왔었다.

위에서는 walk, swim, fly을 각각 객체에서 구현을 해주어야 한다.

(같은 새도 수영이 가능한 새가 있다…)

이걸 mixin으로 구현하면 쉽게 해결이 된다.

선형화


mixin은 위와 같이 stack처럼 차곡차곡 쌓인다.

그렇기에 마지막에 쌓인 내용이 override해버린다.

즉, 순서가 중요하다.

이미지

위 상속에서 복잡하던 구조를 mixin을 통해서 구현하였다.

사용법


mixin은 abstract나 mixin 선언을 통해서 사용 가능하다.

mixin { }
abstract { }

동물 예제


abstract class Animal {}

abstract class Mammal extends Animal {}

abstract class Bird extends Animal {}

abstract class Fish extends Animal {}

abstract class Walker {
// This class is intended to be used as a mixin, and should not be
// extended directly.
	factory Walker._() => null;

	void walk() {
		print("I'm walking");
	}
}

abstract class Swimmer {
// This class is intended to be used as a mixin, and should not be
// extended directly.
	factory Swimmer._() => null;

	void swim() {
		print("I'm swimming");
	}
}

abstract class Flyer {
// This class is intended to be used as a mixin, and should not be
// extended directly.
	factory Flyer._() => null;

	void fly() {
		print("I'm flying");
	}
}

class Dolphin extends Mammal with Swimmer {}

class Bat extends Mammal with Walker, Flyer {}

class Cat extends Mammal with Walker {}

class Dove extends Bird with Walker, Flyer {}

class Duck extends Bird with Walker, Swimmer, Flyer {}

class Shark extends Fish with Swimmer {}

class FlyingFish extends Fish with Swimmer, Flyer {}

On keyword


mixin에 보면 On 키워드가 있다. 뒤집는 방식으로 객체를 사용하게 해주는 트릭이다.

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...
}

위와 같은 경우 Hunt에는 Reptile(swim, crawl, bite가 mixin된 mixin)이 없지만

Reptile내부 내용을 사용해서 구현이 필요한 경우 on 키워드를 사용해

Reptile이 내부에 있다는 가정으로 구현이 가능하다.

단, 저렇게 사용할 경우 with로 넣어주는 곳에 Reptile이 존재해야한다.