Python의 객체지향 프로그래밍: 클래스, 객체, 상속 이해하기

  • 카카오톡 공유하기
  • 네이버 블로그 공유하기
  • 네이버 밴드에 공유하기
  • 페이스북 공유하기
  • 트위터 공유하기
  • 링크 복사하기

객체지향 프로그래밍(OOP)은 현대 프로그래밍의 핵심 패러다임 중 하나입니다. Python은 이러한 객체지향 프로그래밍을 완벽하게 지원하는 언어로, 복잡한 프로그램을 구조화하고 재사용 가능한 코드를 작성하는 데 큰 도움을 줍니다. 이 글에서는 Python의 객체지향 프로그래밍의 핵심 개념인 클래스, 객체, 상속에 대해 알아보겠습니다.

1. 클래스(Class)란 무엇인가?

클래스는 객체를 생성하기 위한 템플릿 또는 청사진이라고 생각할 수 있습니다. 클래스는 데이터(속성)와 이 데이터를 조작하는 메서드(함수)를 정의합니다. Python에서 클래스는 class 키워드를 사용하여 정의합니다.

class Car:
    # 클래스 변수
    wheels = 4
    
    # 초기화 메서드 (생성자)
    def __init__(self, make, model, year, color):
        # 인스턴스 변수
        self.make = make
        self.model = model
        self.year = year
        self.color = color
        self.speed = 0
    
    # 인스턴스 메서드
    def accelerate(self, increment):
        self.speed += increment
        return f"{self.make} {self.model}의 속도가 {self.speed}km/h로 증가했습니다."
    
    def brake(self, decrement):
        if self.speed - decrement >= 0:
            self.speed -= decrement
        else:
            self.speed = 0
        return f"{self.make} {self.model}의 속도가 {self.speed}km/h로 감소했습니다."
    
    def get_description(self):
        return f"{self.year}년식 {self.color} {self.make} {self.model}"

위 예제에서 Car 클래스는 자동차의 속성(제조사, 모델, 연식, 색상, 속도)과 행동(가속, 감속, 설명 가져오기)을 정의합니다.

2. 객체(Object)란 무엇인가?

객체는 클래스의 인스턴스(instance)입니다. 클래스가 붕어빵 틀이라면, 객체는 그 틀로 만든 실제 붕어빵이라고 생각할 수 있습니다. 클래스를 정의한 후에는 그 클래스의 인스턴스를 생성하여 사용할 수 있습니다.

# Car 클래스의 인스턴스(객체) 생성
my_car = Car("현대", "그랜저", 2022, "검정")
your_car = Car("기아", "K5", 2021, "흰색")

# 객체의 메서드 호출
print(my_car.get_description())  # 출력: 2022년식 검정 현대 그랜저
print(my_car.accelerate(30))     # 출력: 현대 그랜저의 속도가 30km/h로 증가했습니다.
print(your_car.get_description())  # 출력: 2021년식 흰색 기아 K5

# 객체의 속성 접근
print(my_car.color)  # 출력: 검정
my_car.color = "빨강"  # 속성 값 변경
print(my_car.color)  # 출력: 빨강

위 예제에서 my_caryour_carCar 클래스의 서로 다른 인스턴스(객체)입니다. 각 객체는 자신만의 속성 값을 가지고 있으며, 클래스에 정의된 메서드를 사용할 수 있습니다.

3. 상속(Inheritance)이란 무엇인가?

상속은 기존 클래스의 속성과 메서드를 새로운 클래스가 재사용할 수 있게 해주는 메커니즘입니다. 이를 통해 코드 재사용성을 높이고 계층적인 관계를 표현할 수 있습니다.

상속에서는 다음과 같은 용어를 사용합니다:

  • 부모 클래스(Parent class) 또는 기본 클래스(Base class): 상속을 제공하는 클래스
  • 자식 클래스(Child class) 또는 파생 클래스(Derived class): 다른 클래스로부터 상속받는 클래스
# 부모 클래스
class Vehicle:
    def __init__(self, make, model, year):
        self.make = make
        self.model = model
        self.year = year
    
    def start_engine(self):
        return f"{self.make} {self.model}의 엔진이 시동됩니다."
    
    def stop_engine(self):
        return f"{self.make} {self.model}의 엔진이 정지됩니다."

# 자식 클래스 (Vehicle 클래스를 상속)
class ElectricCar(Vehicle):
    def __init__(self, make, model, year, battery_capacity):
        # 부모 클래스의 초기화 메서드 호출
        super().__init__(make, model, year)
        self.battery_capacity = battery_capacity
        self.charge_level = 0
    
    # 새로운 메서드 추가
    def charge_battery(self, amount):
        if self.charge_level + amount <= 100:
            self.charge_level += amount
        else:
            self.charge_level = 100
        return f"{self.make} {self.model}의 배터리가 {self.charge_level}% 충전되었습니다."
    
    # 부모 클래스의 메서드 오버라이딩(재정의)
    def start_engine(self):
        return f"{self.make} {self.model}의 전기 모터가 가동됩니다."

위 예제에서 ElectricCar 클래스는 Vehicle 클래스를 상속받습니다. ElectricCar 클래스는 부모 클래스의 모든 속성과 메서드를 상속받으며, 추가로 자신만의 속성과 메서드를 정의할 수 있습니다. 또한, 부모 클래스의 메서드를 오버라이딩(재정의)할 수도 있습니다.

# Vehicle 인스턴스 생성
my_vehicle = Vehicle("토요타", "코롤라", 2020)
print(my_vehicle.start_engine())  # 출력: 토요타 코롤라의 엔진이 시동됩니다.

# ElectricCar 인스턴스 생성
my_tesla = ElectricCar("테슬라", "모델 3", 2022, 75)
print(my_tesla.start_engine())    # 출력: 테슬라 모델 3의 전기 모터가 가동됩니다.
print(my_tesla.charge_battery(80))  # 출력: 테슬라 모델 3의 배터리가 80% 충전되었습니다.
print(my_tesla.stop_engine())     # 출력: 테슬라 모델 3의 엔진이 정지됩니다. (상속받은 메서드)

4. 다중 상속(Multiple Inheritance)

Python은 다중 상속을 지원합니다. 즉, 한 클래스가 여러 부모 클래스로부터 상속받을 수 있습니다.

class Battery:
    def __init__(self, capacity):
        self.capacity = capacity
        self.level = 0
    
    def charge(self, amount):
        if self.level + amount <= 100:
            self.level += amount
        else:
            self.level = 100
        return f"배터리가 {self.level}% 충전되었습니다."

class SolarPanel:
    def __init__(self, efficiency):
        self.efficiency = efficiency
    
    def generate_power(self, sunlight_hours):
        return sunlight_hours * self.efficiency

# 다중 상속
class SolarElectricCar(ElectricCar, SolarPanel):
    def __init__(self, make, model, year, battery_capacity, panel_efficiency):
        ElectricCar.__init__(self, make, model, year, battery_capacity)
        SolarPanel.__init__(self, panel_efficiency)
    
    def solar_charge(self, sunlight_hours):
        power_generated = self.generate_power(sunlight_hours)
        charge_amount = power_generated / self.battery_capacity * 100
        return self.charge_battery(charge_amount)

위 예제에서 SolarElectricCar 클래스는 ElectricCarSolarPanel 두 클래스를 모두 상속받습니다. 이를 통해 두 클래스의 모든 기능을 사용할 수 있습니다.

5. 객체지향 프로그래밍의 장점

  • 코드 재사용성: 상속을 통해 기존 코드를 재사용할 수 있습니다.
  • 모듈화: 관련된 데이터와 기능을 하나의 단위(클래스)로 묶을 수 있습니다.
  • 유지보수성: 코드가 구조화되어 있어 유지보수가 용이합니다.
  • 확장성: 기존 코드를 수정하지 않고도 새로운 기능을 추가할 수 있습니다.
  • 캡슐화: 데이터와 그 데이터를 처리하는 메서드를 하나로 묶고, 외부에서의 접근을 제어할 수 있습니다.

결론

Python의 객체지향 프로그래밍은 복잡한 소프트웨어 시스템을 설계하고 구현하는 데 강력한 도구입니다. 클래스를 통해 데이터와 기능을 캡슐화하고, 객체를 통해 실제 인스턴스를 생성하며, 상속을 통해 코드 재사용성을 높일 수 있습니다. 이러한 개념들을 잘 이해하고 활용하면 더 효율적이고 유지보수하기 쉬운 코드를 작성할 수 있습니다.

객체지향 프로그래밍은 처음에는 복잡해 보일 수 있지만, 실제 프로젝트에 적용해보면 그 강력함을 체감할 수 있습니다.


게시됨

카테고리

작성자

댓글

답글 남기기

이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다