상속(Inheritance)은 객체 지향 프로그래밍(OOP)의 핵심 개념 중 하나로, 부모 클래스가 가진 속성(상태)과 메서드(행위)를 자식 클래스가 물려받는 것을 의미합니다.
이를 통해 코드 재사용성을 높이고, 계층적인 구조를 통해 클래스 간의 관계를 명확히 표현할 수 있습니다.
하지만 단순히 "물려받는 것" 이상의 의미를 가지며, 다형성(Polymorphism)이 성립할 때 진정으로 올바른 상속이라 할 수 있습니다.
다형성이란?
"하나의 형태가 다양한 형태로 동작하는 것"
상속 관계에서 다형성이란, 자식 클래스의 객체가 부모 클래스의 형태로 사용될 수 있는 것을 뜻합니다. 예를 들어, 자식 클래스가 부모 클래스의 타입으로 묶여 있을 때도 부모 클래스에서 정의된 행위를 동일하게 수행하거나, 자식 클래스에 특화된 동작을 수행할 수 있어야 합니다.
💡 만약 BMW라는 클래스가 엔진 클래스를 상속한다면 과연 그것은 정상적인 설계가 맞을까요?
다형성이 성립하지 않기 때문에 잘못된 상속이라고 할 수 있습니다.
즉, 다형성이란 BMW(자식)에게 너 엔진(부모)이야? 라고 물었을 때 어, 나 엔진이야 라고 대답할 수 있어야 올바른 상속입니다.
***자동차와 엔진의 관계는 부모-자식 관계가 아니라 구성(Composition) 관계에 해당
상속
class Burger {
String? name;
Burger() {
print('버거 생성자 호출()');
}
}
class CheeseBurger extends Burger {
CheeseBurger(String name) {
print('치즈버거 생성자 호출()');
// this.name = name;
super.name = name;
}
}
void main() {
CheeseBurger ch = CheeseBurger('불고기치즈버거');
print(' name 호출 : ${ch.name}');
// 문제 - 사용시점, 치즈버거 생성자 호출시 인수로 전달 받은 문자열을
// 부모 클래스인 name 변수에 저장하고 싶다면 어떻게 코드를 작성하지?
}
super 키워드
// super 키워드는 자식이 부모의 객체를 참조할 수 있는 키워드 입니다.
class Burger {
String? name;
Burger() {
print('버거 생성자 호출()');
}
}
class CheeseBurger extends Burger {
CheeseBurger(String name) {
print('치즈버거 생성자 호출()');
// this.name = name;
super.name = name;
}
}
void main() {
CheeseBurger ch = CheeseBurger('불고기치즈버거');
print(' name 호출 : ${ch.name}');
// 문제 - 사용시점, 치즈버거 생성자 호출시 인수로 전달 받은 문자열을
// 부모 클래스인 name 변수에 저장하고 싶다면 어떻게 코드를 작성하지?
}
initialize 문법과 super 키워드
// super 키워드는 자식이 부모의 객체를 참조할 수 있는 키워드 입니다.
class Burger {
String? name;
// 기본 생성자 - 매개변수 있다면 ....
Burger(String? name) {
print('버거 생성자 호출()');
this.name = name;
}
}
class CheeseBurger extends Burger {
// 자식에 태어나기 전에 부모가 먼저 태어나야 자식이 존재할 수 있다.
// dart 에서 부모 생성자에 매개변수가 있다면
// 이니셜라이즈 키워드와 super 키워드를 통해 값을 전달 한다.
// 이니셜라이즈 키워드를 살펴 보자.
CheeseBurger(String? name) : super(name) {
print('치즈버거 생성자 호출()');
}
}
void main() {
CheeseBurger burger = CheeseBurger('불고기치즈버거');
print(burger.name);
}
상속은 코드 재사용성과 계층적인 설계를 가능하게 하는 강력한 도구입니다.
하지만, 올바르게 사용하지 않으면 불필요한 의존성과 설계상의 문제가 생길 수 있습니다.
항상 다형성이 성립하는지를 확인하고, 적합하지 않을 경우 컴포지션과 같은 다른 설계 패턴을 고려하는 것이 중요합니다.
아래의 문헌을 참고하여 작성된 포스팅입니다.
최주호, 김근호, 이지원(공저) 『만들면서 배우는 플러터 앱 프로그래밍』, 앤써북, 2023.
'Flutter > Dart' 카테고리의 다른 글
[DART] dart의 추상 클래스 (1) | 2025.01.07 |
---|---|
[DART] OOP 연관관계와 Mixin (1) | 2025.01.07 |
[DART] Sound Null Safety in dart (0) | 2025.01.06 |
[DART] 클래스와 인스턴스 (2) | 2025.01.03 |
[DART] 익명함수와 화살표함수 (1) | 2025.01.03 |