본 글은 [Do it! 깡샘의 플러터&다트 프로그래밍] 의 내용을 발췌한 것입니다.
책의 모든 내용을 저자 직강으로 진행한 강의는 ssamz.com 에서 들으실 수 있습니다.
믹스인 알아보기
일반 클래스는 class라는 예약어로 선언하고 변수와 함수, 생성자를 정의할 수 있습니다. 그런데 믹스인은 mixin이라는 예약어로 선언합니다.
mixin MyMixin {
int data1 = 10;
void myFun1() {
print('MyMixin... myFun()...');
}
}
믹스인에는 변수와 함수를 선언할 수 있지만 클래스가 아니므로 생성자는 선언할 수 없습니다.
mixin MyMixin {
int data1 = 10;
static int data2 = 20;
MyMixin() {} // 오류
void myFun1() {
print('MyMixin... myFun()...');
}
static void myFun2() {}
}
믹스인은 생성자를 가질 수 없으므로 객체를 생성할 수도 없습니다.
mixin MyMixin {
int data1 = 10;
void myFun1() {
print('MyMixin... myFun()...');
}
}
main() {
var obj = MyMixin() ; // 오류
}
믹스인 사용하기
생서자를 가질 수 없어서 객체로 만들 수 없는 믹스인은 어떤 쓸모가 있을까요? 다트를 비롯해 대부분의 객체지향 언어에서는 다중 상속을 지원하지 않습니다. 즉, 하나의 클래스만 상속받을 수 있습니다. 따라서 다음과 같은 코드는 오류가 발생합니다.
class Super1 {}
class Super2 {}
class MySub extends Super1, Super2 { // 오류
}
그런데 여러 클래스에 선언된 멤버를 상속한 것처럼 이용하고 싶을 때가 있습니다. 이때 믹스인을 사용합니다. 믹스인을 사용하면 클래스를 상속하지 않고도 믹스인에 선언한 멤버를 다른 클래스에서 사용할 수 있습니다. 이때 with 예약어를 사용합니다.
오른쪽 코드에서는 MyClass에 with My Mixin을 선언해 믹스인의 멤버를 사용합니다.
mixin MyMixin {
int mixinData = 10;
void mixInFun() {
print('MyMixin... mixInFun()...');
}
}
class MyClass with MyMixin {
void sayHello() {
print('data : $mixinData');
mixInFun();
}
}
결국 다트는 다중 상속을 제공하지 않는 대신 다른 클래스에서 사용할 수 있는 멤버를 선언할 수 있도록 믹스인을 제공합니다. 다음 코드는 마치 다중 상속처럼 자식 클래스에서 믹스인을 사용한 예입니다.
mixin MyMixin {
int mixinData = 10;
void mixInFun() {
print('MyMixin... mixInFun()...');
}
}
class MySuper {
int superData = 20;
void superFun() {
print('MySuper... superFun()');
}
}
class MyClass extends MySuper with MyMixin {
void sayHello() {
print('class data : $superData, mixin data : $mixinData');
mixInFun();
superFun();
}
}
main() {
var obj = MyClass();
obj.sayHello();
}
또한 with 예약어로 믹스인을 이용하는 클래스의 객체는 믹스인 타입으로 사용할 수 있습니다.
class MyClass with MyMixin {}
main() {
var obj = MyClass();
if (obj is MyMixin) {
print('obj is MyMixin');
} else {
print('obj is not MyMixin');
}
MyMixin obj2 = MyClass();
}
믹스인 사용 제약
믹스인은 모든 클래스에서 with 예약어로 사용할 수 있습니다. 그런데 특정 타입의 클래스에서만 사용하도록 제한할 수도 있습니다. 이때는 믹스인 선언부에 on 예약어로 해당 타입을 지정합니다.
다음 코드에서는 MyMixin에 on으로 MySuper를 지정했습니다. 따라서 MySuper를 상속받은 MyClass에서는 MyMixin을 사용할 수 있지만, MySomeClass에서는 사용할 수 없습니다.
mixin MyMixin on MySuper {
}
class MySuper {
}
class MyClass extends MySuper with MyMixin { // 성공
}
class MySomeClass with MyMixin { // 오류
}
with로 클래스 이용하기
앞에서 알아본 것처럼 with 예약어는 믹스인을 사용할 때 이용합니다. 하지만 클래스도 with로 이용할 수 있습니다. 다음 코드에서는 MyClass를 선언하면서 with로 SomeClass를 연결했으므로 MyClass에서 SomeClass의 멤버를 이용할 수 있습니다.
class SomeClass {
int someData = 10;
}
class MyClass with SomeClass {
void sayHello() {
print('someData : $someData');
}
}
보통은 클래스를 extends로 상속받아 이용하지만 믹스인처럼 with로도 이용할 수 있습니다. 즉, 어떤 클래스에서 다른 클래스나 믹스인에 선언된 멤버를 사용할 때 with를 사용할 수 있습니다.
이렇게 보면 믹스인과 클래스는 별 차이가 없는 것 같습니다. 그러나 클래스는 객체를 생성할 수 있지만, 믹스인은 객체를 생성할 수 없습니다. 결국 믹스인은 독립적으로 이용할 수 없으며 다른 클래스에서 공통으로 사용할 변수나 함수를 믹스인에 담아 두고 필요한 클래스에서 with로 연결해서 사용합니다.
또한 with 에약어로 사용할 클래스에는 생성자를 선언할 수 없습니다. 따라서 다음 코드를 실행하면 User 클래스는 생성자를 선언하므로 믹스인으로 사용할 수 없다는 오류가 발생합니다.
class User {
User() {}
}
class MyClass with User { // 오류
}
책의 모든 내용을 저자 직강으로 진행한 강의는 ssamz.com 에서 들으실 수 있습니다.
'flutter' 카테고리의 다른 글
플러터 - Text Widget (0) | 2023.03.13 |
---|---|
플러터 - StatefulWidget (0) | 2023.03.13 |
플러터 - factory constructor (0) | 2023.03.13 |
플러터 - named constructor (0) | 2023.03.13 |
플러터 - for, in, switch case, try on catch finally (2) | 2023.03.13 |