상속
상속(inheritance)
예를 들어 까치와 참새, 제비는 모두 ‘조류’라는 특징을 가지고 있습니다.
즉, 까치와 참새, 제비는 모두 서로 다른 ‘종’이지만 하늘을 날 수 있는 ‘조류’라는 공통점을 가지고 있는 것입니다.
이러한 개념을 클래스에 적용시켜 보면, 까치와 참새, 제비라는 클래스는 모두 ‘조류’ 클래스의 특징을 ‘상속받았다’고 할 수 있습니다.
이것이 바로 객체 지향 프로그래밍의 대표적인 개념 중 하나인 상속(inheritance)의 개념이며, 이를 이용하면 이미 존재하는 클래스의 모든 특징을 물려받는 새로운 클래스를 손쉽게 생성할 수 있습니다.
이러한 상속은 기존 클래스를 직접 수정하지 않고, 기능을 추가하거나 변경하고 싶을 때 유용하게 사용할 수 있습니다.
이때 이미 존재하던 클래스를 부모 클래스(parent class) 또는 기초 클래스(base class)라고 부르며, 상속을 통해 새롭게 생성되는 클래스를 자식 클래스(child class) 또는 파생 클래스(derived class)라고 부릅니다.
클래스 상속하기
파이썬에서 클래스를 선언할 때 다른 클래스를 상속받고 싶다면, 소괄호(())를 사용하여 그 안에 상속받고 싶은 클래스명을 넣어 전달함으로써 해당 클래스의 모든 멤버를 상속받을 수 있습니다.
문법
class 자식클래스명(부모클래스명):
예제
class Bird:
def __init__(self):
self.flying = True
def birdsong(self):
print("새소리")
class Sparrow(Bird):
def birdsong(self):
print("짹짹")
my_pet = Sparrow()
print(my_pet.flying)
my_pet.birdsong()
실행 결과
True
짹짹
위 예제의 9번 라인에서는 Sparrow 클래스가 Bird 클래스를 상속받아 선언되었으며, 14번 라인에서는 Sparrow 클래스의 my_pet 인스턴스를 생성하고 있습니다.
이때 Sparrow 클래스는 Bird 클래스를 상속받았기 때문에, Sparrow 클래스에서는 선언하지 않았지만 부모 클래스인 Bird 클래스에는 존재하는 flying 속성을 16번 라인처럼 자유롭게 사용할 수 있는 것입니다.
메소드 오버라이딩(method overriding)
앞선 예제의 10번 라인에서 Sparrow 클래스는 부모 클래스인 Bird 클래스에서 선언한 birdsong() 메소드와 같은 이름의 메소드를 또다시 선언하고 있습니다. 이처럼 상속 관계에 있는 부모 클래스에서 이미 정의된 메소드를 자식 클래스에서 같은 이름으로 재정의하는 것을 메소드 오버라이딩(method overriding)이라고 합니다.
자식 클래스에서는 상속받은 부모 클래스의 메소드를 그대로 사용해도 되고, 추가하거나 변경해야 할 사항이 생기면 메소드 오버라이딩을 통해 메소드를 재정의하여 사용할 수도 있는 것입니다.
예제
class Bird:
def __init__(self):
self.flying = True
def birdsong(self):
print("새소리")
class Sparrow(Bird):
def birdsong(self):
print("짹짹")
class Chicken(Bird):
def __init__(self):
self.flying = False
my_sparrow = Sparrow()
my_chicken = Chicken()
my_sparrow.birdsong()
my_chicken.birdsong()
실행 결과
짹짹
새소리
위의 예제에서 Sparrow 클래스와 Chicken 클래스는 모두 Bird 클래스를 상속받습니다.
하지만 Sparrow 클래스는 birdsong() 메소드를 재정의하고, Chicken 클래스는 birdsong() 메소드를 재정의하지 않습니다.
따라서 23번 라인에서 Chicken 클래스의 인스턴스는 부모 클래스인 Bird 클래스의 birdsong() 메소드를 그대로 사용하는 것을 확인할 수 있습니다.
접근 제어(access control)
자바나 C++과 같은 대부분의 객체 지향 프로그래밍 언어에서는 사용자가 굳이 알 필요가 없는 정보는 되도록 사용자로부터 숨겨야 한다는 정보 은닉(data hiding)의 원칙에 따라 접근 제어자(access modifier)라는 것을 사용합니다.
접근 제어자를 사용하면 클래스 외부에서의 직접적인 접근을 허용하지 않는 속성이나 메소드를 선언할 수 있기 때문에 정보 은닉(data hiding)과 캡슐화(encapsulation)를 구체화할 수 있습니다.
다음은 C++ 언어에서 사용할 수 있는 접근 제어자와 그 설명입니다.
접근 제어자 | 설명 |
---|---|
public |
선언된 클래스 멤버는 외부로 공개되며, 해당 객체를 사용하는 프로그램 어디에서나 직접 접근할 수 있음. |
private |
선언된 클래스 멤버는 외부에 공개되지 않으며, 외부에서는 직접 접근할 수 없음. |
protected |
선언된 클래스 멤버는 부모 클래스에 대해서는 public 멤버처럼 취급되며, 외부에서는 private 멤버처럼 취급됨. |
하지만 파이썬에서는 이러한 접근 제어자를 사용하지 않고도, 변수나 메소드의 이름을 작성할 때 그 작명법(naming)에 따라 접근 제어를 구현하고 있습니다.
C++ 접근 제어자 | 파이썬 |
---|---|
public |
멤버 이름에 어떠한 언더스코어(_)도 포함되지 않음. 예) name |
private |
멤버 이름 앞에 두 개의 언더스코어(__)가 접두사로 포함됨. 예) __name |
protected |
멤버 이름 앞에 한 개의 언더스코어(_)가 접두사로 포함됨. 예) _name |