Topic 6: 상속 기초 - 클래스의 확장 🌱
🎯 학습 목표
상속의 기본 개념을 이해하고, 부모 클래스로부터 자식 클래스를 만들어 코드를 재사용하고 기능을 확장할 수 있습니다.
🧬 상속(Inheritance)이란?
일상생활의 상속
실생활 비유:
- 부모 → 자식: 외모, 성격, 능력을 물려받음
- 자동차 → 스포츠카: 기본 기능 + 추가 기능
- 스마트폰 → 게이밍폰: 기본 기능 + 게임 특화 기능
프로그래밍에서의 상속
상속은 기존 클래스(부모)의 속성과 메서드를 새로운 클래스(자식)가 물려받는 것입니다.
# 부모 클래스 (기본 동물)
class Animal:
def __init__(self, name):
self.name = name
self.energy = 100
def eat(self):
self.energy += 20
print(f"{self.name}가 먹이를 먹습니다. 에너지: {self.energy}")
def sleep(self):
self.energy += 30
print(f"{self.name}가 잠을 잡니다. 에너지: {self.energy}")
# 자식 클래스 (강아지 - Animal을 상속)
class Dog(Animal): # Animal 클래스를 상속받음
def bark(self): # 강아지만의 고유 기능
print(f"{self.name}가 멍멍 짖습니다!")
# 자식 클래스 (고양이 - Animal을 상속)
class Cat(Animal): # Animal 클래스를 상속받음
def meow(self): # 고양이만의 고유 기능
print(f"{self.name}가 야옹 웁니다!")
# 강아지와 고양이는 Animal의 기능을 모두 사용 가능
dog = Dog("뽀삐")
cat = Cat("나비")
# 부모 클래스의 메서드 사용
dog.eat() # 뽀삐가 먹이를 먹습니다. 에너지: 120
dog.sleep() # 뽀삐가 잠을 잡니다. 에너지: 150
# 자식 클래스의 고유 메서드 사용
dog.bark() # 뽀삐가 멍멍 짖습니다!
cat.meow() # 나비가 야옹 웁니다!
👨👩👧👦 상속의 기본 문법
기본 상속 구조
class 부모클래스:
# 부모의 속성과 메서드
class 자식클래스(부모클래스):
# 부모의 모든 기능 + 자식만의 추가 기능
실용적인 예시: 사람과 직업
class Person:
"""기본 사람 클래스"""
def __init__(self, name, age):
self.name = name
self.age = age
self.energy = 100
def introduce(self):
print(f"안녕하세요! 저는 {self.name}이고, {self.age}세입니다.")
def eat(self):
self.energy += 20
print(f"{self.name}가 식사를 했습니다. 에너지: {self.energy}")
def rest(self):
self.energy += 30
print(f"{self.name}가 휴식을 취했습니다. 에너지: {self.energy}")
class Student(Person):
"""학생 클래스 - Person을 상속"""
def __init__(self, name, age, grade):
super().__init__(name, age) # 부모 클래스의 __init__ 호출
self.grade = grade
self.score = 0
def study(self):
self.energy -= 20
self.score += 10
print(f"{self.name}가 공부했습니다! 점수: {self.score}, 에너지: {self.energy}")
def take_exam(self):
if self.energy >= 30:
self.energy -= 30
exam_score = min(100, self.score + 20)
print(f"{self.name}의 시험 점수: {exam_score}점")
return exam_score
else:
print(f"{self.name}는 너무 피곤해서 시험을 볼 수 없습니다!")
return 0
class Teacher(Person):
"""선생님 클래스 - Person을 상속"""
def __init__(self, name, age, subject):
super().__init__(name, age) # 부모 클래스의 __init__ 호출
self.subject = subject
self.students = []
def teach(self):
self.energy -= 15
print(f"{self.name} 선생님이 {self.subject}를 가르칩니다! 에너지: {self.energy}")
def add_student(self, student_name):
self.students.append(student_name)
print(f"{student_name} 학생이 {self.name} 선생님의 수업에 등록되었습니다!")
# 사람들 생성
student = Student("kim_cheolsu", 16, 2)
teacher = Teacher("lee_younghee", 35, "수학")
# 모든 사람이 할 수 있는 행동 (상속받은 기능)
student.introduce() # 안녕하세요! 저는 kim_cheolsu이고, 16세입니다.
teacher.introduce() # 안녕하세요! 저는 lee_younghee이고, 35세입니다.
student.eat() # kim_cheolsu가 식사를 했습니다.
teacher.rest() # lee_younghee가 휴식을 취했습니다.
# 각자만의 고유한 행동
student.study() # kim_cheolsu가 공부했습니다!
student.take_exam() # kim_cheolsu의 시험 점수: 30점
teacher.teach() # lee_younghee 선생님이 수학를 가르칩니다!
teacher.add_student("kim_cheolsu") # kim_cheolsu 학생이 lee_younghee 선생님의 수업에 등록되었습니다!
🔧 super() 함수
super()의 역할
super()
는 부모 클래스의 메서드를 호출할 때 사용하는 특별한 함수입니다.
class Vehicle:
"""탈것 기본 클래스"""
def __init__(self, brand, model, year):
self.brand = brand
self.model = model
self.year = year
self.speed = 0
self.fuel = 100
def start_engine(self):
print(f"{self.brand} {self.model}의 엔진이 시작됩니다!")
def accelerate(self, amount):
self.speed += amount
self.fuel -= amount * 0.1
print(f"가속! 현재 속도: {self.speed}km/h, 연료: {self.fuel:.1f}%")
def stop(self):
self.speed = 0
print(f"{self.brand} {self.model}이 정지했습니다.")
class Car(Vehicle):
"""자동차 클래스"""
def __init__(self, brand, model, year, doors):
super().__init__(brand, model, year) # 부모의 __init__ 호출
self.doors = doors # 자동차만의 추가 속성
def open_door(self):
print(f"{self.doors}개 문 중 하나를 열었습니다.")
def honk(self):
print("빵빵! 경적을 울립니다!")
class Motorcycle(Vehicle):
"""오토바이 클래스"""
def __init__(self, brand, model, year, engine_size):
super().__init__(brand, model, year) # 부모의 __init__ 호출
self.engine_size = engine_size # 오토바이만의 추가 속성
def wheelie(self):
if self.speed > 30:
print("앞바퀴 들기 묘기를 부립니다! 🏍️")
else:
print("더 빠른 속도가 필요합니다!")
# 다양한 탈것들
my_car = Car("현대", "소나타", 2023, 4)
my_motorcycle = Motorcycle("혼다", "CBR", 2022, 600)
# 공통 기능들 (상속받은 기능)
my_car.start_engine() # 현대 소나타의 엔진이 시작됩니다!
my_car.accelerate(50) # 가속! 현재 속도: 50km/h
my_car.open_door() # 4개 문 중 하나를 열었습니다.
my_car.honk() # 빵빵! 경적을 울립니다!
my_motorcycle.start_engine() # 혼다 CBR의 엔진이 시작됩니다!
my_motorcycle.accelerate(40) # 가속! 현재 속도: 40km/h
my_motorcycle.wheelie() # 앞바퀴 들기 묘기를 부립니다! 🏍️
🎭 메서드 오버라이딩(Method Overriding)
부모의 메서드를 자식이 다시 정의
class Animal:
def __init__(self, name, species):
self.name = name
self.species = species
def make_sound(self):
print(f"{self.name}가 소리를 냅니다.")
def move(self):
print(f"{self.name}가 움직입니다.")
def introduce(self):
print(f"저는 {self.species} {self.name}입니다.")
class Dog(Animal):
def __init__(self, name, breed):
super().__init__(name, "강아지") # species를 "강아지"로 고정
self.breed = breed
def make_sound(self): # 메서드 오버라이딩
print(f"{self.name}가 멍멍 짖습니다!")
def move(self): # 메서드 오버라이딩
print(f"{self.name}가 꼬리를 흔들며 뛰어갑니다!")
def fetch(self): # 강아지만의 고유 메서드
print(f"{self.name}가 공을 가져옵니다!")
class Cat(Animal):
def __init__(self, name, color):
super().__init__(name, "고양이") # species를 "고양이"로 고정
self.color = color
def make_sound(self): # 메서드 오버라이딩
print(f"{self.name}가 야옹 웁니다!")
def move(self): # 메서드 오버라이딩
print(f"{self.name}가 우아하게 걸어갑니다!")
def climb(self): # 고양이만의 고유 메서드
print(f"{self.name}가 높은 곳으로 올라갑니다!")
class Bird(Animal):
def __init__(self, name, wing_span):
super().__init__(name, "새")
self.wing_span = wing_span
def make_sound(self): # 메서드 오버라이딩
print(f"{self.name}가 짹짹 웁니다!")
def move(self): # 메서드 오버라이딩
print(f"{self.name}가 날개를 펼쳐 하늘을 날아갑니다!")
def fly(self): # 새만의 고유 메서드
print(f"{self.name}가 {self.wing_span}cm 날개를 펼치고 비행합니다!")
# 다양한 동물들
dog = Dog("뽀삐", "골든리트리버")
cat = Cat("나비", "흰색")
새 = Bird("피피", 25)
print("=== 자기소개 ===")
dog.introduce() # 저는 강아지 뽀삐입니다.
cat.introduce() # 저는 고양이 나비입니다.
새.introduce() # 저는 새 피피입니다.
print("\n=== 소리내기 ===")
dog.make_sound() # 뽀삐가 멍멍 짖습니다!
cat.make_sound() # 나비가 야옹 웁니다!
새.make_sound() # 피피가 짹짹 웁니다!
print("\n=== 움직이기 ===")
dog.move() # 뽀삐가 꼬리를 흔들며 뛰어갑니다!
cat.move() # 나비가 우아하게 걸어갑니다!
새.move() # 피피가 날개를 펼쳐 하늘을 날아갑니다!
print("\n=== 고유 행동 ===")
dog.fetch() # 뽀삐가 공을 가져옵니다!
cat.climb() # 나비가 높은 곳으로 올라갑니다!
새.fly() # 피피가 25cm 날개를 펼치고 비행합니다!
🎮 실전 예시: 게임 캐릭터 시스템
class GameCharacter:
"""게임 캐릭터 기본 클래스"""
def __init__(self, name, level=1):
self.name = name
self.level = level
self.hp = 100
self.max_hp = 100
self.experience = 0
def attack(self, target):
damage = self.calculate_damage()
print(f"{self.name}가 {target}에게 {damage} 데미지를 입혔습니다!")
return damage
def calculate_damage(self):
return 10 + self.level * 2
def level_up(self):
self.level += 1
self.max_hp += 20
self.hp = self.max_hp
print(f"🎉 {self.name}가 레벨업! Lv.{self.level}")
def show_status(self):
print(f"=== {self.name} 상태 ===")
print(f"레벨: {self.level}")
print(f"HP: {self.hp}/{self.max_hp}")
print(f"경험치: {self.experience}")
class Warrior(GameCharacter):
"""전사 클래스"""
def __init__(self, name, level=1):
super().__init__(name, level)
self.hp = 150 # 전사는 체력이 더 많음
self.max_hp = 150
self.armor = 10
def calculate_damage(self):
# 전사는 더 강한 공격력
return 15 + self.level * 3
def shield_block(self):
print(f"{self.name}가 방패로 공격을 막습니다! 🛡️")
return self.armor
def berserker_mode(self):
print(f"{self.name}가 광전사 모드 발동! 🔥")
return self.calculate_damage() * 2
class Mage(GameCharacter):
"""마법사 클래스"""
def __init__(self, name, level=1):
super().__init__(name, level)
self.hp = 80 # 마법사는 체력이 적음
self.max_hp = 80
self.mana = 100
self.max_mana = 100
def calculate_damage(self):
# 마법사는 마나 기반 공격
return 12 + self.level * 4
def cast_spell(self, spell_name):
if self.mana >= 20:
self.mana -= 20
damage = self.calculate_damage() * 1.5
print(f"{self.name}가 {spell_name} 마법을 시전! ✨ 데미지: {damage}")
return damage
else:
print(f"{self.name}의 마나가 부족합니다!")
return 0
def meditate(self):
self.mana = min(self.max_mana, self.mana + 30)
print(f"{self.name}가 명상으로 마나를 회복합니다. 마나: {self.mana}")
def show_status(self):
super().show_status() # 부모의 show_status 호출
print(f"마나: {self.mana}/{self.max_mana}") # 마법사만의 추가 정보
class Archer(GameCharacter):
"""궁수 클래스"""
def __init__(self, name, level=1):
super().__init__(name, level)
self.arrows = 50
self.accuracy = 0.8
def calculate_damage(self):
# 궁수는 정확도 기반 공격
base_damage = 8 + self.level * 2
if self.accuracy > 0.7:
return int(base_damage * 1.3) # 높은 정확도 보너스
return base_damage
def shoot_arrow(self, target):
if self.arrows > 0:
self.arrows -= 1
damage = self.calculate_damage()
print(f"{self.name}가 {target}에게 화살을 발사! 🏹 데미지: {damage}")
print(f"남은 화살: {self.arrows}발")
return damage
else:
print(f"{self.name}의 화살이 떨어졌습니다!")
return 0
def reload_arrows(self):
self.arrows = 50
print(f"{self.name}가 화살을 다시 장전했습니다! 🏹")
def show_status(self):
super().show_status() # 부모의 show_status 호출
print(f"화살: {self.arrows}발") # 궁수만의 추가 정보
print(f"정확도: {self.accuracy*100:.0f}%")
# 다양한 캐릭터들 생성
warrior = Warrior("드래곤슬레이어", 5)
mage = Mage("아이스퀸", 4)
archer = Archer("로빈후드", 3)
print("=== 캐릭터 상태 ===")
warrior.show_status()
print()
mage.show_status()
print()
archer.show_status()
print("\n=== 전투 시뮬레이션 ===")
warrior.attack("오크")
warrior.berserker_mode()
mage.cast_spell("파이어볼")
mage.meditate()
archer.shoot_arrow("슬라임")
archer.shoot_arrow("고블린")
🔍 isinstance()와 상속
상속 관계 확인하기
class Animal:
pass
class Dog(Animal):
pass
class Cat(Animal):
pass
# 객체들 생성
dog = Dog()
cat = Cat()
# isinstance로 상속 관계 확인
print(f"강아지는 Dog? {isinstance(dog, Dog)}") # True
print(f"강아지는 Animal? {isinstance(dog, Animal)}") # True
print(f"강아지는 Cat? {isinstance(dog, Cat)}") # False
print(f"고양이는 Cat? {isinstance(cat, Cat)}") # True
print(f"고양이는 Animal? {isinstance(cat, Animal)}") # True
print(f"고양이는 Dog? {isinstance(cat, Dog)}") # False
🚨 자주 발생하는 오류
오류 1: super() 호출 누락
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
class Student(Person):
def __init__(self, name, age, grade):
# ❌ super() 호출 누락
# self.name = name
# self.age = age
# 부모의 초기화가 누락됨!
# ✅ 올바른 방법
super().__init__(name, age)
self.grade = grade
오류 2: 메서드 오버라이딩 실수
class Animal:
def make_sound(self):
print("동물이 소리를 냅니다")
class Dog(Animal):
# ❌ 메서드 이름 실수
# def make_sounds(self): # 's' 추가로 다른 메서드가 됨
# print("멍멍!")
# ✅ 정확한 메서드 이름
def make_sound(self):
print("멍멍!")
💡 퀴즈: 상속 기초 이해도 체크
Q1. 상속에서 자식 클래스가 할 수 있는 것은?
- 부모 클래스의 속성과 메서드 사용
- 새로운 속성과 메서드 추가
- 부모 클래스의 메서드 오버라이딩
- 위의 모든 것
💡 정답 확인
정답: 4번 (위의 모든 것)
자식 클래스는 부모의 모든 기능을 사용할 수 있고, 새로운 기능을 추가하거나 기존 기능을 재정의할 수 있습니다.
Q2. super()의 역할은?
- 자식 클래스를 호출한다
- 부모 클래스의 메서드를 호출한다
- 새로운 클래스를 생성한다
- 클래스를 삭제한다
💡 정답 확인
정답: 2번 (부모 클래스의 메서드를 호출한다)
super()
는 자식 클래스에서 부모 클래스의 메서드를 호출할 때 사용합니다.
Q3. 다음 코드에서 결과는?
class Animal:
def speak(self):
return "동물이 소리를 냅니다"
class Dog(Animal):
def speak(self):
return "멍멍!"
dog = Dog()
print(dog.speak())
- “동물이 소리를 냅니다”
- “멍멍!”
- 오류 발생
- 아무것도 출력되지 않음
💡 정답 확인
정답: 2번 (“멍멍!”)
자식 클래스의 speak()
메서드가 부모 클래스의 메서드를 오버라이딩했기 때문에 자식 클래스의 메서드가 실행됩니다.
✅ 상속 기초 마스터 체크리스트
✅ 상속 기초 마스터 체크리스트
🎊 Unit 6 완주!
상속까지 학습하면서 객체지향 프로그래밍의 핵심을 모두 마스터했습니다!
🏆 Unit 6에서 배운 내용
- 클래스 기본: 클래스와 객체의 개념, 객체 생성
- 속성과 메서드: 객체의 정보와 행동 구현
- 생성자와 초기화: 매개변수로 객체 초기화
- 클래스 활용: 실전 프로젝트에서 클래스 활용
- 고급 기능: 클래스 변수, 정적 메서드, 특수 메서드
- 상속: 코드 재사용과 클래스 확장
🚀 이제 할 수 있는 것들
- 객체지향적 사고: 현실 세계를 클래스와 객체로 모델링
- 코드 재사용: 상속을 통한 효율적인 코드 작성
- 복잡한 시스템 설계: 여러 클래스가 협력하는 프로그램
- 실전 프로젝트: 게임, 은행 시스템, 쇼핑몰 등 구현
🌟 객체지향 프로그래밍의 핵심 원칙
- 캡슐화: 관련된 데이터와 기능을 클래스로 묶기
- 상속: 기존 클래스를 확장하여 새로운 클래스 만들기
- 다형성: 같은 인터페이스로 다른 동작 구현
- 추상화: 복잡한 내부 구조를 숨기고 필요한 기능만 제공
축하합니다! 이제 여러분은 파이썬 객체지향 프로그래밍의 기초를 완전히 마스터했습니다! 🎊
클래스와 상속을 활용하여 더욱 구조적이고 재사용 가능한 코드를 작성할 수 있습니다. 이는 큰 프로젝트를 개발할 때 매우 중요한 기술입니다! 🚀
Last updated on