flutter

Dart mixin 이란?

paulaner80 2019. 4. 3. 10:34
반응형

1. 믹스인이 필요한 이유


C#같은 언어에는 믹스인이 없습니다. 

다음 클래스 상속 다이어그램을 살펴 보겠습니다.







Animal이라는 슈퍼클래스가 있습니다. Mammal, Bird, Fish가 그 클래스를 상속합니다. 가장 마지막에는 콘크리트 클래스들이 있습니다. 작은 사각형은 행동을 나타냅니다. 예를 들어, 파란색 사각형은이 동작을하는 클래스의 인스턴스가 수영 할 수 있음을 나타냅니다. 어떤 동물들은 공통적 인 행동을 공유합니다. 이러한 종류의 동작은이 분류와 직각이므로 수퍼 클래스에서 이러한 동작을 구현할 수 없습니다.

 

한 클래스가 하나 이상의 수퍼 클래스를 가질 수 있다면 쉽게 할 수 있습니다. 

세 클래스(Walker, Swimmer, Flyer)를 만든 후 콘크리트클래스에게 이 클래스를 적절히 상속시켜주기 만하면 됩니다. 그러나 Dart에서는 모든 클래스에는(Object 제외) 하나의 슈퍼 클래스만 있습니다.

 

Walker 클래스를 상속하는 대신 인터페이스 인 것처럼 구현할 수 있지만 여러 클래스에서 동작을 구현해야하므로 좋은 해결책은 아닙니다.

 

여러 클래스 계층에서 클래스의 코드를 재사용 할 수있는 방법이 필요합니다.

 

믹스 인은 여러 클래스 계층에서 클래스의 코드를 재사용하는 방법입니다. -  Dart.org

라고 나와 있습니다. 쉬워보입니다.

 

 

제약조건 (???? Dart2.1만 보면 되나 ???)

믹스인 기능에는 몇가지 제약조건이 있습니다.

 

Dart 1.13 이상은 Object 이외의 클래스에서 확장 할 수있는 mixin을 지원하며 super.method ()를 호출 할 수 있습니다. 이 지원은 기본적으로 다트 VM 및 분석기에서 플래그 뒤에 만 사용할 수 있습니다. 보다 구체적으로 명령 줄 분석기의 - supermixin 플래그 뒤에 있습니다. 또한 클라이언트가 구성 할 수있는 옵션이있는 분석 서버에서도 사용할 수 있습니다. Dart2js와 dartdevc는 수퍼 믹스를 지원하지 않습니다.

 

Dart 2.1에서 mixins는 제한이 적을 것으로 예상됩니다. 예를 들어, Flutter는 super ()를 호출하고 Object가 아닌 클래스에서 확장하는 mixins를 지원하지만 구문은 모든 Dart SDK에 표시되기 전에 변경 될 것으로 예상됩니다. 자세한 내용은 mixin 사양을 참조하십시오.

 



2. 문법


2-1. 정의

믹스인은 일반적인 클래스 선언을 통해 암시 적으로 정의됩니다.

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




2-2. 확장막기

믹스인을 인스턴스화되거나 확장되지 않도록하려면 다음과 같이 정의 할 수 있습니다.

abstract class Walker {
// 이 클래스는 믹스 인으로 사용하기위한 것이므로 직접 확장해서는 안됩니다.
factory Walker._() => null;

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

class A extends Walker {} //The superclass 'Walker' doesn't have a zero argument constructor.



2-3. 여러개 믹스인 사용하기

믹스인을 사용하려면  with 키워드를 쓰고 다음에 하나  또는 여러개의 믹스인 이름을 써줍니다.

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

class Flyer {
void fly() {
print("I'ma flying");
}
}

class Mammal {}

class Bird {}

class Cat extends Mammal with Walker {}

class Dove extends Bird with Walker, Flyer {}

main(List<String> args) {
Cat cat = Cat();
Dove dove = Dove();

cat.walk();

dove.walk();
dove.fly();
}



2-4 on 키워드

다트의 믹스인을 사용해 여러가지 기능을 사용할 수 있지만. 살펴볼만한 중요한 키워드가 있습니다. on은 믹스인의 사용을 선언된 클래스를 확장하거나 구현하는 클래스로만 제한하는데 사용됩니다. on 키워드를 사용하려면 mixin 키워드를 사용해서 믹스인을 선언해야합니다.


class A {}

mixin X on A {}

class Y on A{}//에러

class p extends A with X {}

class Q extends X {} //에러


3. 디테일


다음의 결과는 무엇일까요? AB 클래스와 BA 클래스 모두 A 및 B 믹스로 P 클래스를 확장하지만 다른 순서로 확장합니다. 

class A {
String getMessage() => 'A';
}

class B {
String getMessage() => 'B';
}

class P {
String getMessage() => 'P';
}

class AB extends P with A, B {}

class BA extends P with B, A {}

main(List<String> args) {
String result = '';

AB ab = AB();
result += ab.getMessage();

BA ba = BA();
result += ba.getMessage();

print(result);
}



정답은 BA 입니다.

믹스인에서는 선언된 순서가 중요합니다.



4.선형화

믹스인은 믹스인을 구현하는 클래스 위에 놓습니다.

슈퍼클래스의 옆이 아니라 위쪽을 쌓아올리기 때문에 모호성이 없습니다.

 

최종 상속 다이어그램은 아래처럼 나타낼 수 있습니다.






AB와 P 사이에 새로운 클래스가 생성됩니다.이 새로운 클래스는 수퍼 클래스 P와 클래스 A와 B 사이의 혼합입니다.

 

이렇게하면 다중상속이 없습니다.

믹스인은 다중 상속을 얻는 방법이 아닙니다.  믹스인은 상태와 동작을 추상화하고 재사용하기 위한 방법입니다. 이것은 클래스 확장에서 얻은 재사용과 비슷하지만 선형이기 때문에 단일 상속과 호환됩니다.

기억해야할 중요한 것은 믹스인이 선언된순서는 상속체인을 나타낸다는 것입니다.



타입


믹스인 어플리케이션 객체의 타입은 무엇일까요? 보통 부모의 하위타입니다. 그리고 믹스인 이름의 하위타입입니다. 


main(List<String> args) {
String result = '';

AB ab = AB();

print(ab is P);
print(ab is A);
print(ab is B);

BA ba = BA();

print(ba is P);
print(ba is A);
print(ba is B);
}


결과

true

true

true

true

true

true 





5. 자세한설명

각 믹스인 애플리케이션은 새로운 클래스를 생성합니다. 또한 새로운 인터페이스도 생성합니다 

(모든 Dart 클래스도 인터페이스로도 정의하기 때문에). 

설명 된 것처럼 새로운 클래스는 수퍼 클래스를 확장하고 mixin 클래스 멤버의 복사본을 포함하지만 mixin 클래스 인터페이스도 구현합니다.


대부분의 경우, mixin-application 클래스 나 인터페이스를 참조 할 방법이 없습니다.


"Super with Mixin" 클래스는 "class C extends Super with Mixin {}"처럼 선언 된 클래스의 익명 슈퍼 클래스에 불과합니다.


"class CSuper = Super with Mixin {}"와 같이 mixin 응용 프로그램의 이름을 지정하면 mixin 응용 프로그램 클래스와 해당 인터페이스를 참조 할 수 있으며 Super 및 Mixin의 하위 유형이됩니다.



6 믹스인을 언제 사용합니까?



믹스인은 여러클래스에서 동작을 공유할 때 매우 유용합니다. 보통 시리얼라이즈나 퍼시스턴스입니다. 또, 유틸리티 함수를 제공하는 경우도 사용할 수 있습니다. 


이것을 즐기세요. 그러면 새로운 유스케이스를 찾을 수 있을 것입니다.


Mixins은 동일한 클래스 계층 구조를 공유하지 않는 여러 클래스에서 동작을 공유하려는 경우 또는 수퍼 클래스에서 이러한 동작을 구현하는 것이 타당하지 않을 때 매우 유용합니다.


일반적으로 직렬화 (예 : jaguar_serializer보기) 또는 지속성의 경우입니다. 그러나 믹스 인을 사용하여 일부 유틸리티 기능 (예 : Flutter의 RenderSliverHelpers)을 제공 할 수도 있습니다.


이 기능으로 시간을내어 새로운 유스 케이스를 찾을 수있을 것입니다. 무국적 mixins에 자신을 제한하지 마십시오, 당신은 절대적으로 변수를 저장할 수 있고 그들을 사용할 수 있습니다!



7.진화하는 믹스인

abstract class Super {
void method() {
print("Super");
}
}

class MySuper implements Super {
void method() {
print("MySuper");
}
}

mixin Mixin on Super {
void method() {
super.method();
print("Sub");
}
}

class Client extends MySuper with Mixin {}

void main() {
Client().method();
}


출력

MySuper

Sub 



13 행에서 18 행까지의 mixin 선언은 Super에 대한 수퍼 클래스 제한을 나타냅니다. 믹스 인이 슈퍼에서 제공하는 기능을 사용하기 때문에이 믹스 인을 클래스에 적용하려면이 클래스가 슈퍼 클래스를 확장하거나 구현해야합니다.


8. 동물예제 완성



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








그외.........................



실험1 : 아래코드의 출력은 믹스인의 것을 출력한다.

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

class Walker2 {
void walk() {
print("I'm walking, too");
}
}

class Alpaca extends Walker with Walker2 {}

main(List<String> args) {
Alpaca alpaca = Alpaca();
alpaca.walk();
}



I'm walking, too 



실험2 : 아래가 같이 하면 오버라이드하라는 에러가 생기지 않는다.

class Walker2 {
void walk() {
print("I'm walking, too");
}
}

abstract class IWalker {
void walk();
}

class Lama extends IWalker with Walker2 {}






출처 : https://medium.com/flutter-community/dart-what-are-mixins-3a72344011f3





'flutter' 카테고리의 다른 글

Dart에서 stream 만들기  (0) 2019.04.04
dart  (0) 2019.04.03
RxDart 관련 내용들  (0) 2019.03.29
Dart mxins  (0) 2019.03.27
Flutter - 스트림. 다트에서 비동기 프로그래밍  (0) 2019.03.27