PYTHON/중급학습

[중급 5편] 클래스 상속과 다형성 실전.zip

Kim.Sung 2025. 5. 13. 21:49

파이썬의 객체지향 프로그래밍에서 핵심 개념인 "상속"과 "다형성"은 코드의 재사용성과 확장성을 높이는 데 매우 유용합니다. 이번 글에서는 상속의 구조, super() 함수의 역할, 다형성 개념, 실무 활용까지 단계별로 정리합니다.




✅ 1. 클래스 상속이란?

기존 클래스의 기능을 그대로 물려받고, 필요한 부분만 확장하거나 수정하여 새로운 클래스를 만드는 구조입니다.  
코드의 중복을 줄이고, 유지보수를 효율적으로 할 수 있습니다.

예시:

class Animal:
    def __init__(self, name):
        self.name = name

    def speak(self):
        print(f"{self.name}가 소리를 냅니다.")

class Dog(Animal):
    def speak(self):
        print(f"{self.name}가 멍멍 짖습니다.")

class Cat(Animal):
    def speak(self):
        print(f"{self.name}가 야옹 웁니다.")

dog = Dog("초코")
cat = Cat("나비")
dog.speak()  # 초코가 멍멍 짖습니다.
cat.speak()  # 나비가 야옹 웁니다.

---

✅ 2. super() 함수

자식 클래스에서 부모 클래스의 메서드(특히 생성자)를 호출할 때 사용하는 내장 함수입니다.  
복잡한 상속 구조에서도 부모의 기능을 그대로 활용할 수 있어, 반복 코드를 줄여줍니다.

예시:

class Animal:
    def __init__(self, name):
        self.name = name

class Bird(Animal):
    def __init__(self, name, can_fly):
        super().__init__(name)
        self.can_fly = can_fly

    def info(self):
        fly_status = "날 수 있음" if self.can_fly else "날 수 없음"
        print(f"{self.name}: {fly_status}")

bird1 = Bird("참새", True)
bird1.info()  # 참새: 날 수 있음

---

✅ 3. 메서드 오버라이딩

자식 클래스에서 부모 클래스의 메서드를 **같은 이름으로 다시 정의**하면, 그 자식 클래스에 맞는 동작으로 덮어씁니다.

예시:

class Animal:
    def sound(self):
        print("동물의 소리")

class Dog(Animal):
    def sound(self):
        print("멍멍")

class Cat(Animal):
    def sound(self):
        print("야옹")

for a in [Dog(), Cat()]:
    a.sound()  # 멍멍 / 야옹

---

✅ 4. 다형성 (Polymorphism)

"동일한 인터페이스를 통해 서로 다른 객체를 동일하게 다룰 수 있다"는 개념입니다.  
즉, 여러 객체가 공통 메서드를 가지고 있을 때, 그 메서드를 호출만 해도 객체에 따라 알아서 동작이 달라집니다.

def make_sound(animal: Animal):
    animal.sound()

make_sound(Dog())  # 멍멍
make_sound(Cat())  # 야옹

실무에서는 다양한 하위 클래스 객체를 리스트에 넣고, 반복문으로 같은 메서드를 호출하여 다르게 동작시키는 경우가 많습니다.

---

✅ 5. 실무 활용 팁

- **상속 계층은 2~3단계로 얕게 유지하는 게 유지보수에 유리합니다.**
- **공통 기능은 상위 클래스에, 특수한 동작은 하위 클래스에서 정의합니다.**
- **super()를 적극 활용하면 중복된 초기화 코드를 줄일 수 있습니다.**
- **다형성은 if-else 분기를 줄이고, 확장 가능한 구조를 설계하는 데 매우 유리합니다.**

---

✅ 6. 간단한 실전 시나리오: 알림 시스템

class Notifier:
    def notify(self, message):
        print("기본 알림:", message)

class EmailNotifier(Notifier):
    def notify(self, message):
        print(f"[이메일] {message}")

class SMSNotifier(Notifier):
    def notify(self, message):
        print(f"[SMS] {message}")

def send_alert(notifier: Notifier, msg):
    notifier.notify(msg)

notifiers = [EmailNotifier(), SMSNotifier()]
for n in notifiers:
    send_alert(n, "서버 오류 발생")  # 각기 다른 방식으로 메시지 발송

---

정리:  
상속은 "기반 코드 재활용", 다형성은 "유연한 확장"입니다.  
복잡한 로직도 이 두 개념만 잘 써도 깔끔하고 확장성 있는 구조로 바꿀 수 있습니다.