학습
Dart 상속과 다형성
Dart 상속과 다형성 — 중급
상속과 다형성
1. 도입 (왜 배워야 하는가)
상속과 다형성은 객체지향 프로그래밍(OOP)의 두 가지 중요한 개념입니다. 이 두 가지를 이해하면 코드 재사용성, 유지보수성 및 확장성을 향상시킬 수 있습니다. 예를 들어, 쇼핑몰 애플리케이션에서 다양한 상품을 다룰 때, 상속을 활용하면 반복적인 코드를 줄일 수 있습니다. 만약 이 개념을 모르고 디자인을 한다면, 유사한 코드가 여러 번 반복되어 코드가 복잡해지고 오류가 발생할 가능성이 높아집니다.
2. 핵심 개념 설명
상속
상속은 한 클래스가 다른 클래스의 속성과 메서드를 물려받는 것입니다. 예를 들어, '동물'이라는 클래스가 있을 때 '개'와 '고양이'는 '동물' 클래스를 상속받을 수 있습니다. 이때 '개'와 '고양이'는 '동물'의 속성과 메서드를 공유합니다.
다형성
다형성은 다양한 클래스의 객체가 동일한 인터페이스를 사용하여 서로 다른 방식으로 동작할 수 있게 해주는 기능입니다. 예를 들어, '동물' 클래스의 '소리 내기' 메서드를 '개'는 "멍멍", '고양이'는 "야옹"으로 구현할 수 있습니다.
| 용어 | 정의 |
|---|---|
| 상속 | 클래스 간의 관계로, 자식 클래스가 부모 클래스의 특성을 물려받는 것 |
| 다형성 | 동일한 메서드 이름을 가지고 있지만, 각기 다른 클래스에서 다르게 동작하는 것 |
3. 기본 코드 예제
다음은 상속과 다형성을 활용한 간단한 코드 예제입니다.
class Animal {
void sound() {
print("동물의 소리");
}
}
class Dog extends Animal {
@override
void sound() {
print("멍멍");
}
}
class Cat extends Animal {
@override
void sound() {
print("야옹");
}
}
void main() {
Animal myDog = Dog();
Animal myCat = Cat();
myDog.sound(); // 멍멍
myCat.sound(); // 야옹
}
실행 결과
멍멍
야옹
코드 한 줄씩 동작 설명
class Animal: 'Animal' 클래스를 정의합니다.void sound(): 기본 소리 메서드를 정의합니다.class Dog extends Animal: 'Dog' 클래스가 'Animal' 클래스를 상속받습니다.@override void sound(): 'Dog' 클래스에서 'sound()' 메서드를 재정의합니다.class Cat extends Animal: 'Cat' 클래스도 'Animal' 클래스를 상속받습니다.@override void sound(): 'Cat' 클래스에서 'sound()' 메서드를 재정의합니다.void main(): 프로그램의 시작점인 메인 메서드입니다.Animal myDog = Dog();: 'Dog' 객체를 'Animal' 타입으로 생성합니다.Animal myCat = Cat();: 'Cat' 객체를 'Animal' 타입으로 생성합니다.myDog.sound();: 'Dog' 객체의 'sound()' 메서드를 호출합니다.myCat.sound();: 'Cat' 객체의 'sound()' 메서드를 호출합니다.- 잘못된 코드:
- 올바른 코드:
- 잘못된 코드:
- 올바른 코드:
- 상속을 통해 코드 재사용성을 높일 수 있다.
- 다형성을 활용하면 동일한 메서드를 다양한 방식으로 구현할 수 있다.
- 상속과 다형성을 통해 애플리케이션의 유지보수성과 확장성을 향상시킬 수 있다.
- 다음에 학습하면 좋은 주제: 인터페이스와 추상 클래스, 믹스인(Mixin) 사용법.
4. 실전 활용 예제
예제 1: 쇼핑몰 장바구니 구현
쇼핑몰에서 다양한 상품을 장바구니에 추가할 때, 상품의 종류에 따라 가격을 계산할 수 있습니다.
abstract class Product {
double getPrice();
}
class Clothing extends Product {
@override
double getPrice() {
return 20.0; // 의류 가격
}
}
class Electronics extends Product {
@override
double getPrice() {
return 200.0; // 전자제품 가격
}
}
void main() {
List<Product> cart = [Clothing(), Electronics()];
double totalPrice = cart.fold(0, (sum, item) => sum + item.getPrice());
print("총 가격: \$${totalPrice}");
}
실행 결과
총 가격: $220.0
예제 2: 게임 캐릭터 구현
게임에서 다양한 캐릭터가 서로 다른 능력을 발휘할 수 있습니다.
abstract class Character {
void attack();
}
class Warrior extends Character {
@override
void attack() {
print("전사가 공격합니다!");
}
}
class Mage extends Character {
@override
void attack() {
print("마법사가 공격합니다!");
}
}
void main() {
List<Character> characters = [Warrior(), Mage()];
for (var character in characters) {
character.attack();
}
}
실행 결과
전사가 공격합니다!
마법사가 공격합니다!
5. 흔한 실수와 주의사항
실수 1: 메서드 오버라이드 시 @override 생략
class Dog extends Animal {
void sound() { // @override가 없음
print("멍멍");
}
}
class Dog extends Animal {
@override
void sound() {
print("멍멍");
}
}
실수 2: 상속 관계를 잘못 이해하기
class Dog extends Cat { // Dog가 Cat를 상속받음
}
class Dog extends Animal { // Dog가 Animal을 상속받음
}