믹스인 vs 상속
Coddy Dart 여정의 객체 지향 프로그래밍 섹션에 포함된 레슨 — 110개 중 54번째.
이제 믹스인(mixins)이 어떻게 작동하는지 배웠으니, 상속(inheritance) 대신 언제 믹스인을 사용해야 하는지 명확히 정리해 보겠습니다. 핵심적인 차이는 이들이 표현하는 관계에 있습니다.
상속은 "is-a" 관계를 나타냅니다. Dog는 Animal입니다. 서브클래스는 부모의 전문화된 버전이며, 하나의 클래스만 확장할 수 있습니다.
반면, 믹스인(Mixins)은 "할 수 있는(can-do)" 관계를 나타냅니다. Dog는 수영을 할 수 있지만, 수영이 개를 정의하는 것은 아닙니다.
// 상속: Dog는 Animal입니다
class Animal {
String name;
Animal(this.name);
}
class Dog extends Animal {
Dog(String name) : super(name);
}
// 믹스인: Dog는 수영을 할 수 있습니다 (하지만 수영으로 정의되지는 않습니다)
mixin Swimming {
void swim() => print('Swimming');
}
class Dog extends Animal with Swimming {
Dog(String name) : super(name);
}클래스들이 근본적인 정체성을 공유하고 부모 클래스에 생성자가 필요한 경우에는 상속을 사용하세요. 공통 조상을 공유하지 않는 클래스들에 기능을 추가하고 싶을 때는 믹스인을 사용하세요.
| 특징 | 상속 | 믹스인 |
|---|---|---|
| 관계 | is-a | can-do |
| 제한 | 단일 부모만 가능 | 여러 믹스인 가능 |
| 생성자 | 허용됨 | 허용되지 않음 |
| 사용 사례 | 특수화 | 공유 동작 |
가장 좋은 점은 무엇일까요? 하나의 클래스를 확장하고 여러 기능을 믹스인하는 두 가지 방식을 모두 결합하여, 클래스에 필요한 기능을 정확하게 부여할 수 있습니다.
챌린지
쉬움상속과 믹스인(mixins)을 언제 사용해야 하는지 보여주는 작업자 시스템을 구축해 보겠습니다. "is-a(이다)" 관계를 위한 기본 클래스와 "can-do(할 수 있다)" 능력을 위한 믹스인을 만들고, 이 두 가지 접근 방식이 어떻게 함께 작동하는지 보여주기 위해 결합해 볼 것입니다.
코드를 세 개의 파일로 구성합니다:
worker.dart: 모든 작업자의 핵심 정체성을 설정하는 기본 클래스를 정의합니다:String name과String department속성을 가진Worker클래스. 두 값을 모두 받는 생성자를 포함하세요.[name] works in [department]를 출력하는introduce()메서드를 추가하세요.
skills.dart: 작업자가 가질 수 있는 능력("can-do" 관계)을 나타내는 믹스인을 정의합니다:Writing code...를 출력하는writeCode()메서드가 있는CanCode믹스인Creating design...을 출력하는createDesign()메서드가 있는CanDesign믹스인Leading the team...을 출력하는leadTeam()메서드가 있는CanManage믹스인
main.dart: 두 파일을 모두 임포트하고 상속과 믹스인을 결합한 특수 작업자 유형을 만듭니다:Worker를 확장(extends)하고CanCode믹스인을 사용하는Developer클래스Worker를 확장하고CanCode와CanManage믹스인을 모두 사용하는TechLead클래스'Engineering'부서의'Alice'라는 이름의Developer를 생성하세요.'Engineering'부서의'Bob'이라는 이름의TechLead를 생성하세요.- Alice의 경우:
introduce()를 호출한 다음writeCode()를 호출하세요. - 빈 줄을 하나 출력하세요.
- Bob의 경우:
introduce(),writeCode(),leadTeam()을 차례로 호출하세요.
Developer와 TechLead가 모두 작업자(상속)이면서도, 서로 다른 일(믹스인)을 할 수 있음에 주목하세요. TechLead는 다중 상속 없이도 여러 능력을 결합할 수 있습니다.
예상 출력:
Alice works in Engineering
Writing code...
Bob works in Engineering
Writing code...
Leading the team...치트 시트
상속은 "is-a" 관계(서브클래스는 부모의 전문화된 버전임)를 나타내는 반면, 믹스인은 정체성을 정의하지 않고 기능을 추가하는 "can-do" 관계를 나타냅니다.
// 상속: Dog는 Animal입니다 (IS-A)
class Animal {
String name;
Animal(this.name);
}
class Dog extends Animal {
Dog(String name) : super(name);
}
// 믹스인: Dog는 수영할 수 있습니다 (CAN-DO)
mixin Swimming {
void swim() => print('Swimming');
}
class Dog extends Animal with Swimming {
Dog(String name) : super(name);
}| 특징 | 상속 | 믹스인 |
|---|---|---|
| 관계 | is-a | can-do |
| 제한 | 오직 하나의 부모만 가능 | 여러 개의 믹스인 가능 |
| 생성자 | 허용됨 | 허용되지 않음 |
| 사용 사례 | 전문화 | 공유된 동작 |
두 가지 방식을 결합할 수 있습니다. 하나의 클래스를 확장(extend)하고 여러 기능을 믹스인(mix in)할 수 있습니다:
class TechLead extends Worker with CanCode, CanManage {
TechLead(String name, String department) : super(name, department);
}직접 해보기
import 'worker.dart';
import 'skills.dart';
// TODO: Worker를 상속받고 CanCode 믹스인을 사용하는 Developer 클래스를 생성하세요
// TODO: Worker를 상속받고 CanCode와 CanManage 믹스인을 모두 사용하는 TechLead 클래스를 생성하세요
void main() {
// TODO: 'Engineering' 부서의 'Alice'라는 이름의 Developer를 생성하세요
// TODO: Alice에 대해 introduce()를 호출한 다음 writeCode()를 호출하세요
// TODO: 빈 줄을 출력하세요
// TODO: 'Engineering' 부서의 'Bob'이라는 이름의 TechLead를 생성하세요
// TODO: Bob에 대해 introduce(), writeCode(), 그 다음 leadTeam()을 호출하세요
}
이 레슨에는 짧은 퀴즈가 포함되어 있습니다. 레슨을 시작해 문제를 풀고 진행 상황을 기록하세요.