객체지향 프로그래밍 기법에서 사용되는 기법이다. 최대한 간단하게 정리하자면
상위 클래스가 하위 클래스에게 가지고 있는 기능을 공유하여 물려받아 확장(extend)하는 개념.
기능을 물려주는 상위 클래스는 기반 클래스(base class)
혹은 부모 클래스(parent class)
, 슈퍼 클래스(super class)
라고 한다
기능을 물려받는 하위 클래스는 파생 클래스(derived class)
혹은 자식 클래스(child class)
, 서브 클래스(sub class)
라고 한다.
예를들어 내가 자동차와 관련된 코드를 짜고 있고 자동차 클래스를 설계하고 있다고 가정해보자
일반적인 자동차는 바퀴와 창문이 4개씩이다. 그리고 자동차는 달릴수 있고 멈출수도 있다. 이러한 일반적인 자동차의 고유 특징들을 다음과 같이 코드로 표현할 수 있다.
class Car:
def __init__(self):
self.wheel = 4
self.windows = 4
def drive(self):
print("자동차가 달린다")
def stop(self):
print("자동차가 멈췄다")
자동차 인스턴스를 생성하여 자동차 클래스가 가지고 있는 고유 변수들과 메소드들을 전부 호출해보자
car = Car()
print(car.wheel)
print(car.windows)
car.drive()
car.stop()
결과
4
4
자동차가 달린다
자동차가 멈췄다
만약에 내가 여기서 차의 지붕을 접었다 폈다 할 수 있는 컨버터블 카를 만들어야 한다고 가정해보자. 그러면 클래스 메소드에 차의 지붕이 열리는 drop_top() 메소드를 추가할 수 있다.
class Car:
def __init__(self):
self.wheel = 4
self.windows = 4
def drive(self):
print("자동차가 달린다")
def stop(self):
print("자동차가 멈췄다")
# 차 지붕 열기
def drop_top(self):
print("뚜겅이 열린다")
하지만 모든 자동차의 지붕이 접히는것도 아니고 아예 지붕이 접히지 않는 일반적인 자동차들이 훨씬 더 많을 것이다.
그러면 아예 컨버터블 자동차 클래스를 만들어보자. 컨버터블 자동차는 똑같이 바퀴와 창문이 4개라고 치고 일반 자동차처럼 달릴수도, 멈출수도 있다. 기존에 작성했던 자동차 클래스를 그대로 가져오고 거기에 drop_top() 메소드만 추가해준다.
class Car:
def __init__(self):
self.wheel = 4
self.windows = 4
def drive(self):
print("자동차가 달린다")
def stop(self):
print("자동차가 멈췄다")
class Convertable:
def __init__(self):
self.wheel = 4
self.windows = 4
def drive(self):
print("자동차가 달린다")
def stop(self):
print("자동차가 멈췄다")
def drop_top(self):
print("뚜겅이 열린다")
이렇게 하면 컨버터블 클래스에만 drop_top() 메소드가 있으므로 아무 문제될게 없어보이지만, Car 클래스에 있는 모든 메소드를 복사해왔다는 점에서 중복되고 비효율적인 코드를 작성했다고 할 수 있다.
어쩌면 Convertable 클래스도 결국에는 자동차라는 상위 개념에 포함될 수 있다. 따라서 Car 클래스를 부모 클래스, Convertable 클래스를 자식 클래스로 정의해 기존에 작성했던 코드를 수정해보자.
class Car:
def __init__(self):
self.wheel = 4
self.windows = 4
def drive(self):
print("자동차가 달린다")
def stop(self):
print("자동차가 멈췄다")
class Convertable(Car):
def drop_top(self):
print("뚜겅이 열린다")
Convertable 클래스가 Car 클래스를 상속받았다. 따라서 Convertable 클래스는 부모 클래스(Car)로 부터 물려받은 모든 기능을 사용할 수 있다.
convertable = Convertable()
convertable.drive()
print(convertable.wheel)
결과
자동차가 달린다
4
위와 같은 사례에서 알 수 있듯, 상속이라는 개념은 중복되는 기능을 재사용할 수 있어 코드를 효율적으로 관리할 수 있다.
부모 클래스에서 정의한 메소드를 자식 클래스에서 재정의하는 개념
부모 클래스에게서 상속받은 메소드를 새롭게 구현하는 것이다. 예를들어 부모 클래스에서 상속받은 drive() 메소드를 오버라이딩 해보자
class Convertable(Car):
def drop_top(self):
print("뚜겅이 열린다")
def drive(self):
print("컨버터블 자동차가 달린다")
convertable = Convertable()
convertable.drive()
결과
컨버터블 자동차가 달린다