Menu
Coddy logo textTech

믹스인 vs 상속

Coddy Dart 여정의 객체 지향 프로그래밍 섹션에 포함된 레슨 — 110개 중 54번째.

이제 믹스인(mixins)이 어떻게 작동하는지 배웠으니, 상속(inheritance) 대신 언제 믹스인을 사용해야 하는지 명확히 정리해 보겠습니다. 핵심적인 차이는 이들이 표현하는 관계에 있습니다.

상속은 "is-a" 관계를 나타냅니다. DogAnimal입니다. 서브클래스는 부모의 전문화된 버전이며, 하나의 클래스만 확장할 수 있습니다.

반면, 믹스인(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-acan-do
제한단일 부모만 가능여러 믹스인 가능
생성자허용됨허용되지 않음
사용 사례특수화공유 동작

가장 좋은 점은 무엇일까요? 하나의 클래스를 확장하고 여러 기능을 믹스인하는 두 가지 방식을 모두 결합하여, 클래스에 필요한 기능을 정확하게 부여할 수 있습니다.

challenge icon

챌린지

쉬움

상속과 믹스인(mixins)을 언제 사용해야 하는지 보여주는 작업자 시스템을 구축해 보겠습니다. "is-a(이다)" 관계를 위한 기본 클래스와 "can-do(할 수 있다)" 능력을 위한 믹스인을 만들고, 이 두 가지 접근 방식이 어떻게 함께 작동하는지 보여주기 위해 결합해 볼 것입니다.

코드를 세 개의 파일로 구성합니다:

  • worker.dart: 모든 작업자의 핵심 정체성을 설정하는 기본 클래스를 정의합니다:
    • String nameString 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를 확장하고 CanCodeCanManage 믹스인을 모두 사용하는 TechLead 클래스
    • 'Engineering' 부서의 'Alice'라는 이름의 Developer를 생성하세요.
    • 'Engineering' 부서의 'Bob'이라는 이름의 TechLead를 생성하세요.
    • Alice의 경우: introduce()를 호출한 다음 writeCode()를 호출하세요.
    • 빈 줄을 하나 출력하세요.
    • Bob의 경우: introduce(), writeCode(), leadTeam()을 차례로 호출하세요.

DeveloperTechLead가 모두 작업자(상속)이면서도, 서로 다른 일(믹스인)을 할 수 있음에 주목하세요. 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-acan-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()을 호출하세요
}
quiz icon실력 점검

이 레슨에는 짧은 퀴즈가 포함되어 있습니다. 레슨을 시작해 문제를 풀고 진행 상황을 기록하세요.

객체 지향 프로그래밍의 모든 레슨