Menu
Coddy logo textTech

다형성 기초

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

다형성(Polymorphism)은 "여러 가지 형태"를 의미합니다. 이는 서로 다른 클래스의 객체들을 공통된 인터페이스를 통해 다룰 수 있는 능력입니다. 부모 클래스 참조 변수가 있을 때, 이는 어떠한 자식 클래스 객체도 가리킬 수 있으며, 실제 객체 타입에 따라 적절한 메서드가 호출됩니다.

이 기능은 부모 타입을 사용하는 코드를 작성하면서도 모든 자식 타입을 자동으로 올바르게 처리할 수 있기 때문에 매우 강력합니다:

class Animal {
  void speak() => print('Some sound');
}

class Dog extends Animal {
  @override
  void speak() => print('Woof!');
}

class Cat extends Animal {
  @override
  void speak() => print('Meow!');
}

void main() {
  Animal myPet = Dog();  // 부모 타입, 자식 객체
  myPet.speak();  // 출력: Woof!
  
  myPet = Cat();  // 동일한 변수, 다른 객체
  myPet.speak();  // 출력: Meow!
}

변수 myPetAnimal로 선언되었지만, Dog 또는 Cat을 보유합니다. speak()가 호출되면, Dart는 런타임 시 실제 객체 유형을 확인하고 적절한 오버라이드된 메서드를 호출합니다.

이를 통해 모든 하위 클래스에서 작동하는 유연한 함수를 작성할 수 있습니다:

void makeAllSpeak(List<Animal> animals) {
  for (var animal in animals) {
    animal.speak();  // 각 동물은 자신만의 방식으로 소리를 냅니다
  }
}

void main() {
  var pets = [Dog(), Cat(), Dog()];
  makeAllSpeak(pets);
  // 출력: Woof! Meow! Woof!
}

함수는 DogCat에 대해 알 필요가 없습니다. 단지 Animal과 함께 작동할 뿐입니다. 새로운 동물 유형을 추가해도 기존 함수를 변경할 필요가 없으므로 코드를 더 확장 가능하게 만듭니다.

challenge icon

챌린지

쉬움

다형성이 실제로 어떻게 작동하는지 보여주는 악기 시스템을 만들어 보겠습니다. 기본 Instrument 클래스와 여러 악기 유형을 생성한 다음, 구체적인 유형을 알지 못해도 모든 악기 컬렉션이 함께 연주되도록 하는 함수를 작성하게 됩니다.

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

  • instruments.dart: 여기에 악기 계층 구조를 정의합니다:
    • String name 속성과 생성자를 가진 Instrument 클래스. [name] makes a sound를 출력하는 play() 메서드를 포함합니다.
    • Instrument를 상속받고 play()를 오버라이드하여 [name] strums melodically를 출력하는 Guitar 클래스.
    • Instrument를 상속받고 play()를 오버라이드하여 [name] beats rhythmically를 출력하는 Drum 클래스.
    • Instrument를 상속받고 play()를 오버라이드하여 [name] plays harmoniously를 출력하는 Piano 클래스.
    또한 Concert begins!를 출력하고, 리스트를 순회하며 각 악기의 play()를 호출한 뒤, 마지막으로 Concert ends!를 출력하는 performConcert(List<Instrument> instruments) 함수를 만듭니다.
  • main.dart: 악기 파일을 임포트하고 혼합 밴드를 생성하여 다형성을 보여줍니다:
    • 이름이 'Acoustic'Guitar, 이름이 'Snare'Drum, 이름이 'Grand'Piano를 포함하는 List<Instrument> 타입의 리스트를 생성합니다.
    • 이 리스트를 performConcert()에 전달합니다.

performConcert()가 부모 타입인 Instrument와 어떻게 작동하는지, 그리고 각 악기가 어떻게 자신만의 고유한 방식으로 연주되는지 주목해 보세요. 이것이 바로 다형성입니다. 동일한 메서드 호출이 실제 객체 유형에 따라 서로 다른 동작을 생성합니다.

예상 출력:

Concert begins!
Acoustic strums melodically
Snare beats rhythmically
Grand plays harmoniously
Concert ends!

치트 시트

다형성(Polymorphism)은 "여러 형태"를 의미하며, 공통 인터페이스를 통해 서로 다른 클래스의 객체를 다룰 수 있게 해줍니다. 부모 클래스 참조는 모든 자식 클래스 객체를 가리킬 수 있으며, 런타임 시 실제 객체 유형에 따라 올바른 메서드가 호출됩니다.

기본적인 다형성 예제:

class Animal {
  void speak() => print('Some sound');
}

class Dog extends Animal {
  @override
  void speak() => print('Woof!');
}

class Cat extends Animal {
  @override
  void speak() => print('Meow!');
}

void main() {
  Animal myPet = Dog();  // 부모 타입, 자식 객체
  myPet.speak();  // Output: Woof!
  
  myPet = Cat();  // 동일한 변수, 다른 객체
  myPet.speak();  // Output: Meow!
}

다형성을 사용하면 모든 하위 클래스에서 작동하는 유연한 함수를 만들 수 있습니다:

void makeAllSpeak(List<Animal> animals) {
  for (var animal in animals) {
    animal.speak();  // 각 동물은 자신만의 방식으로 소리를 냅니다
  }
}

void main() {
  var pets = [Dog(), Cat(), Dog()];
  makeAllSpeak(pets);
  // Output: Woof! Meow! Woof!
}

이 함수는 DogCat과 같은 특정 자식 클래스에 대해 알 필요 없이 부모 타입인 Animal과 함께 작동합니다. 이는 코드를 더 확장 가능하게 만듭니다. 새로운 타입을 추가해도 기존 함수를 변경할 필요가 없기 때문입니다.

직접 해보기

import 'instruments.dart';

void main() {
  // TODO: 다음을 포함하는 List<Instrument>를 생성하세요:
  // - 이름이 'Acoustic'인 Guitar
  // - 이름이 'Snare'인 Drum
  // - 이름이 'Grand'인 Piano
  
  
  // TODO: 생성한 악기 리스트를 사용하여 performConcert()를 호출하세요
  
}
quiz icon실력 점검

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

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