클래스의 개념과 객체 생성
클래스란?
클래스는 객체를 만들기 위한 '설계도'다. 실제 사물이나 개념을 프로그래밍으로 표현하기 위한 틀이라고 할 수 있다.
예를 들어, 집을 지을 때 설계도가 필요한 것처럼 프로그래밍에서도 객체를 만들기 전에 그 객체가 어떤 속성을 가지고 어떤 기능을 하는지 정의해야 한다. 이러한 정의를 담고 있는 것이 바로 클래스다.
# 강아지 클래스(설계도) 정의
class Dog:
# 초기화 메서드: 객체가 생성될 때 자동으로 호출됨
def __init__(self, name, weight):
self.name = name # 강아지 이름 속성
self.weight = weight # 강아지 무게 속성
# 강아지의 행동을 나타내는 메서드
def bark(self):
return f"{self.name}가 멍멍! 짖는다."
def eat(self):
self.weight += 1
return f"{self.name}은 밥을 먹었다. 이제 {self.weight}kg이 되었다."
객체란?
객체는 클래스를 바탕으로 실제로 생성된 실체다. 같은 클래스로 여러 객체를 만들 수 있으며, 각 객체는 서로 독립적이다.
예를 들어, 같은 설계도(클래스)로 여러 채의 집을 지을 수 있는 것처럼, 하나의 클래스로 여러 객체를 생성할 수 있다.
# Dog 클래스(설계도)로 실제 강아지 객체 생성
maltese = Dog("댕댕일", 3) # 댕댕일이라는 이름의 3kg 강아지 객체
poodle = Dog("댕댕이", 5) # 댕댕이라는 이름의 5kg 강아지 객체
# 강아지 객체 사용하기
print(maltese.name) # 댕댕일
print(poodle.weight) # 5
print(maltese.bark()) # 댕댕일(이)가 와르르왈! 짖는다.
print(poodle.eat()) # 댕댕이(는)은 밥을 먹었다. 이제 6kg이 되었다.
print(poodle.eat()) # 댕댕이(는)은 밥을 먹었다. 이제 7kg이 되었다.
print(poodle.eat()) # 댕댕이(는)은 밥을 먹었다. 이제 8kg이 되었다.
그림으로 이해하는 클래스와 객체
[클래스(설계도): Dog]
+---------------------+
| 속성: |
| - name (이름) |
| - weight (나이) |
| |
| 메서드: |
| - bark() |
| - eat() |
| |
+---------------------+
|
↓ 객체 생성
+-------+ +-------+
| 댕댕일 | | 댕댕이 |
+-------+ +-------+
| name:댕댕일 | name: 댕댕이|
| weight: 3 | weight: 5 |
+-------+ +-------
상속과 다형성
상속이란?
상속은 기존 클래스의 속성과 메서드를 새로운 클래스가 물려받는 것이다. 이를 통해 코드 재사용성을 높이고 관계를 표현할 수 있다.
예를 들어, 모든 동물이 가진 공통 특성을 정의한 클래스가 있고, 그것을 바탕으로 강아지나 새 같은 특정 동물의 클래스를 만들 수 있다.
# 동물(부모) 클래스
class Animal:
def __init__(self, name, age):
self.name = name
self.age = age
def eat(self):
return f"{self.name}이(가) 먹이를 먹는다."
def sleep(self):
return f"{self.name}이(가) 잠을 잔다."
# 강아지(자식) 클래스 - Animal을 상속받음
class Dog(Animal):
# 추가 특성
def __init__(self, name, age, breed):
# 부모 클래스의 초기화 메서드 호출
super().__init__(name, age)
self.breed = breed # 강아지 품종
# 강아지만의 특별한 메서드
def bark(self):
return f"{self.name}이(가) 멍멍! 짖는다."
def wait(self):
return f"{self.name}이(가) 기다린다."
# 새(자식) 클래스 - Animal을 상속받음
class Bird(Animal):
def fly(self):
return f"{self.name}이(가) 퍼드득 날아오른다."
# 객체 생성 및 사용
dog = Dog("댕댕삼", 3, "진돗개")
bird = Bird("앵무", 2)
# 부모 클래스(Animal)의 메서드 사용
print(dog.eat()) # 출력: 댕댕삼이(가) 먹이를 먹는다.
print(bird.sleep()) # 출력: 앵무이(가) 잠을 잔다.
# 각자의 특별한 메서드 사용
print(dog.bark()) # 출력: 댕댕삼이(가) 멍멍! 짖는다.
print(bird.fly()) # 출력: 앵무이(가) 퍼드득 날아오른다.
# 강아지만의 추가 속성
print(dog.breed) # 출력: 진돗개
그림으로 이해하는 상속
[Animal]
+---------------+
| - name |
| - age |
| |
| + eat() |
| + sleep() |
+-------+-------+
^
|
+-------+-------+
| |
[Dog] [Bird]
+---------------+ +---------------+
| - breed | | |
| | | |
| + bark() | | + fly() |
| + wait() | | |
+---------------+ +---------------+
Method Overriding?
메소드 오버라이딩은 부모 클래스에서 정의된 메소드를 자식 클래스에서 재정의하는 기법이다.
예를 들어, '소리 내기'라는 동일한 메소드를 동물마다 다르게 재정의 할 수 있다. ex)강아지는 '멍멍', 고양이는 '야옹', 오리는 '꽥꽥'
# 동물 클래스
class Animal:
def __init__(self, name):
self.name = name
def make_sound(self):
return "울부짖는다."
# 강아지 클래스
class Dog(Animal):
def make_sound(self):
return "멍멍!"
# 고양이 클래스
class Cat(Animal):
def make_sound(self):
return "야옹!"
# 오리 클래스
class Duck(Animal):
def make_sound(self):
return "꽥꽥!"
class Human(Animal):
pass
# 동물들의 소리 출력 함수
def animal_sounds(animals):
for animal in animals:
print(f"{animal.name}: {animal.make_sound()}")
# 여러 동물 객체 생성
dog = Dog("바둑이")
cat = Cat("나비")
duck = Duck("오리")
human = Human("사람")
# 모든 동물의 소리 출력
animals = [dog, cat, duck, human]
animal_sounds(animals)
# 출력:
# 바둑이: 멍멍!
# 나비: 야옹!
# 오리: 꽥꽥!
# 사람: 울부짖는다.
super() 함수와 메서드 호출
super() 함수는 부모 클래스의 메서드를 호출할 때 사용된다. 이를 통해 자식 클래스에서 부모 클래스의 기능을 확장하거나 수정할 수 있다.
class Vehicle:
def __init__(self, make, model, year):
self.make = make
self.model = model
self.year = year
def start_engine(self):
return "엔진 시동!"
def info(self):
return f"{self.year} {self.make} {self.model}"
class ElectricCar(Vehicle):
def __init__(self, make, model, year, battery_capacity):
# 부모 클래스의 __init__ 메서드 호출
super().__init__(make, model, year)
self.battery_capacity = battery_capacity
# 메서드 오버라이딩 + 부모 메서드 확장
def start_engine(self):
# 부모 클래스의 start_engine 메서드 호출 후 추가 기능 구현
parent_result = super().start_engine()
return f"{parent_result} (전기 모터 작동 중...)"
# 부모 메서드 활용 + 확장
def info(self):
# 부모 클래스의 info 메서드 호출 후 추가 정보 포함
basic_info = super().info()
return f"{basic_info} - 배터리: {self.battery_capacity}kWh"
# 객체 생성
tesla = ElectricCar("Tesla", "Model 3", 2023, 75)
# 메서드 호출
print(tesla.start_engine()) # 출력: 엔진 시동! (전기 모터 작동 중...)
print(tesla.info()) # 출력: 2023 Tesla Model 3 - 배터리: 75kWh
예제: 게임 캐릭터 시스템
기본 요구사항
1. 기본 캐릭터 클래스 구현
- Character 클래스를 구현한다.
- 속성:
- name: 캐릭터 이름
- health: 체력(HP)
- power: 공격력
- 메소드:
- __init__(self, name, health, power): 초기화 메소드
- attack(self): 기본 공격 수행 (메시지 반환)
- take_damage(self, damage): 피해를 입는 메소드 (체력 감소 및 메시지 반환)
2. 전사(Warrior) 클래스 구현
- Character 클래스를 상속받아 구현한다.
- 추가 속성:
- armor: 방어력
- 메소드:
- __init__(self, name, health, power, armor): 초기화 메소드 (부모 클래스의 초기화 메소드 호출)
- take_damage(self, damage): 메소드 오버라이딩 - 방어력을 고려한 피해 계산 (부모 클래스의 메소드 호출)
- heavy_attack(self): 전사만의 특수 공격 기능 (공격력의 2배 데미지)
3. 마법사(Wizard) 클래스 구현
- Character 클래스를 상속받아 구현하세요.
- 추가 속성:
- mana: 마나
- 메소드:
- __init__(self, name, health, power, mana): 초기화 메소드 (부모 클래스의 초기화 메소드 호출)
- fireball(self): 파이어볼 마법 (마나 20 소모, 공격력의 3배 데미지)
- heal(self): 치유 마법 (마나 10 소모, 체력 20 회복)
4. 게임 시뮬레이션
- 각 클래스의 객체를 생성하여 다음 동작을 시뮬레이션한다.
- 전사와 마법사의 기본 공격
- 전사의 특수 공격(heavy_attack)
- 마법사의 특수 공격(fireball)
- 전사와 마법사가 피해를 입는 상황
- 마법사의 치유 마법 사용
# 기본 캐릭터 클래스
class Character:
def __init__(self, name, health, power):
self.name = name # 캐릭터 이름
self.health = health # 체력
self.power = power # 공격력
def attack(self):
return f"{self.name}이(가) {self.power}의 공격력으로 공격한다."
def take_damage(self, damage):
self.health -= damage
if self.health <= 0:
return f"{self.name}이(가) 쓰러졌다."
return f"{self.name}이(가) {damage}의 피해를 입었다. 남은 체력: {self.health}"
# 전사 클래스 (Character 상속)
class Warrior(Character):
def __init__(self, name, health, power, armor):
super().__init__(name, health, power)
self.armor = armor # 방어력
# 메서드 오버라이딩
def take_damage(self, damage):
# 방어력 적용하여 피해 감소
actual_damage = max(1, damage - self.armor)
return super().take_damage(actual_damage)
# 전사만의 특별한 능력
def heavy_attack(self):
return f"{self.name}이(가) {self.power * 2}의 강력한 공격을 한다. (체력 -10)"
# 마법사 클래스 (Character 상속)
class Wizard(Character):
def __init__(self, name, health, power, mana):
super().__init__(name, health, power)
self.mana = mana # 마나
# 마법사만의 특별한 능력
def fireball(self):
if self.mana >= 20:
self.mana -= 20
return f"{self.name}이(가) 파이어볼을 사용했다. 적에게 {self.power * 3}의 피해를 입힌다. 남은 마나: {self.mana}"
else:
return f"{self.name}의 마나가 부족하다."
def heal(self):
if self.mana >= 10:
self.mana -= 10
self.health += 20
return f"{self.name}이(가) 치유 마법을 사용했다. 체력이 20 회복되었다. 현재 체력: {self.health}, 남은 마나: {self.mana}"
else:
return f"{self.name}의 마나가 부족하다."
# 게임 캐릭터 객체 생성
warrior = Warrior(name="강철의 기사", health=100, power=15, armor=5)
wizard = Wizard(name="현명한 마법사", health=70, power=10, mana=100)
# 게임 플레이 시뮬레이션
print("=== 게임 시작 ===")
print(warrior.attack()) # 전사의 일반 공격
print(wizard.attack()) # 마법사의 일반 공격
print(warrior.heavy_attack()) # 전사의 특수 공격
print(wizard.fireball()) # 마법사의 특수 공격
print(warrior.take_damage(30)) # 전사가 피해를 입음
print(wizard.take_damage(20)) # 마법사가 피해를 입음
print(wizard.heal()) # 마법사가 치유 마법 사용
print("=== 게임 종료 ===")
'python' 카테고리의 다른 글
파이썬 기초 - Mutable과 Immutable 객체 (0) | 2025.03.19 |
---|---|
파이썬 기초 - Iterable, Iterator, Generator (0) | 2025.03.18 |
파이썬 기초 - 함수 기초 (0) | 2025.03.16 |
파이썬 기초 - 조건문과 반복문 (1) | 2025.03.16 |
파이썬 기초 - 변수와 데이터 타입 (0) | 2025.03.15 |
댓글