서론 #
- 11장에서 본 것 처럼 상속을 코드 재사용의 목적으로 사용하면 변경하기 어렵고 유연하지 못한 설게에 이를 확률이 높아진다.
- 상속의 목적은 코드 재사용이 아닌, 타입 계층을 구조화하기 위해 사용해야 한다.
- 클라이언트 관점에서 인스턴스들을 동일하게 행동하는 그룹으로 묶기 위해서이다.
01. 다형성 #
- 다형성이라는 단어는 많은 형태를 가질 수 있는 능력을 의미한다.
- 다형성의 종류
- 오버로딩 다형성
- 하나의 클래스 안에 동일한 이름의 메서드가 존재하는 경우.
- 인자에 따라 메서드를 선택함.
- 강제 다형성
- 자동적인 타입 변환이나 사용자가 직접 구현한 타입 변환을 이용해 동일한 연산자를 다양한 타입에 사용할 수 있는 방식을 가리킴.
- ‘+’는 숫자의 덧셈이 될 수 있고, 문자열의 연결 연산자로도 사용될 수 있음.
- 매개변수 다형성
- 제네릭 프로그래밍
- List 와 같은 임의의 타입을 선언한 후 사용하는 시점에 구체적인 타입을 지정하는 방식
- 포함 다형성
- 서브타입 다형성
- 메시지가 동일하더라도 수신한 객체의 타입에 따라 실제로 수행하는 행동이 달라지는 능력
- 포함 다형성을 위한 전제조건은 자식 클래스가 부모 클래스의 서브타입이어야 한다는 것이다.
- 상속의 진정한 목적은 코드 재사용이 아니라 다형성을 위한 서브타입 계층 구축이다.
- 포함 다형성을 위해 상속을 사용하는 가장 큰 이유는 상속이 클래스들을 계층으로 쌓아 올린 후 상황에 따라 적절한 메서드를 선택할 수 있는 메커니즘을 제공하기 때문이다.
02. 상속의 양면성 #
- 데이터 관점의 상속 : 부모 클래스의 데이터를 자식 클래스의 인스턴스에 자동으로 포함시키는 것
- 행동 관점의 상속 : 부모 클래스의 메서드를 자식 클래스에 포함
- 하지만 상속의 목적은 코드 재사용이 아니다.
- 상속은 프로그램을 구성하는 개념들을 기반으로 다형성을 가능하게 하는 타입 계층을 구축하기 위한 것이다.
- 타입 계층에 대한 고민 없이 코드를 재사용하기 위해 상속을 사용하면 이해하기 어렵고 유지보수하기 버운 코드가 만들어질 확률이 높다.
03. 업캐스팅과 동적 바인딩 #
업캐스팅 #
- 상속을 이용하면 부모 클래스의 퍼블릭 인터페이스가 자식 클래스의 퍼블릭 인터페이스에 합쳐지기 때문에 부모 클래스의 인스턴스에게 전송할 수 있는 메시지를 자식 클래스의 인스턴스에게 전송할 수 있다.
- 부모 클래스의 인스턴스 대신 자식 클래스의 인스턴스를 사용하더라도 메시지를 처리하는 데는 아무런 문제가 없으며, 컴파일러는 명시적인 타입 변환 없이도 자식 클래스가 부모 클래스를 대체할 수 있게 허용한다.
- 컴파일러 관점에서는 자식 클래스는 아무런 제약 없이 부모를 대체할 수 있다.
- 따라서 부모 클래스와 협력하는 클라이언트는 다양한 자식 클래스의 인스턴스와 또한 협력이 가능하다.
- 이 설계는 유연하며 확장이 용이하다.
동적 바인딩 #
- 함수를 호출하는 전통적인 언어들은 호출될 함수를 컴파일타임에 결정한다.
- 정적 바인딩, 초기 바인딩, 컴파일타임 바인딩이라고도 부름
- 객체향 언어에서는 메시지를 수신했을 때 실행될 메서드가 런타임에 결정된다
04. 동적 메서드 탐색과 다형성 #
- 객체에서 메시지를 받으면 수행할 메서드가 있는지 확인하고, 없다면 상속된 부모 클래스로 올라가서 탐색한다.
- self, super 에 대한 내용
05. 상속 대 위임 #