다형성(Polymorphism)
하나의 추상 인터페이스에 대해 코드를 작성하고 이 추상 인터페이스에 대해 서로 다른 구현을 연결할 수 있는 능력
여러 타입을 대상으로 동작할 수 있는 코드를 작성할 수 있는 방법
유니버셜(Universal) 다형성 |
|
매개변수(Parametric) 다형성 |
클래스의 인스턴스 변수나 메서드의 매개변수 타입을 임의의 타입으로 선언한 후 사용하는 시점에 구체적인 타입으로 지정하는 방식 제네릭 프로그래밍과 관련이 높음 |
포함(Include) 다형성 |
메시지가 동일하더라도 수신한 객체의 타입에 따라 실제로 수행되는 행동이 달라지는 방식 객체지향 프로그래밍에서 가장 널리 알려진 형태의 다형성 상속을 사용 : 어떤 메시지, 어떤 클래스의 인스턴스인지에 따라 처리할 적절한 메서드를 상속 계층 안에서 탐색 서브타입(Subtype) 다형성이라고도 부름 : 자식 클래스가 부모 클래스의 서브타입이어야 함 - 상속의 진정한 목적은 코드 재사용이 아니라 다형성을 위한 서브타입 계층을 구축하는 것 |
임시(Ad Hoc) 다형성 |
|
오버로딩(Overloading) 다형성 |
하나의 클래스 안에 동일한 이름의 메서드가 존재 유사한 작업을 수행하는 메서드의 이름을 통일 |
강제(Coercion) 다형성 |
언어가 지원하는 자동적인 타입 변환이나 사용자가 직접 구현한 타입 변환을 이용해 동일한 연산자를 다양한 타입에 사용할 수 있는 방식 오버로딩 다형성과 강제 다형성을 함께 사용하면 모호해질 수 있음 - 실제로 어떤 메서드가 호출될지 판단하기가 어려워짐 |
상속의 양면성
데이터 관점의 상속 : 부모 클래스에서 정의한 모든 데이터를 자식 클래스의 인스턴스에 포함시킴
행동 관점의 상속 : 데이터뿐만 아니라 부모 클래스에서 정의한 일부 메서드를 자식 클래스에 포함시킴
상속의 목적은 코드 재사용이 아니고, 프로그램을 구성하는 개념들을 기반으로 다형성을 가능하게 하는 타입 계층을 구축하는 것
메서드 오버라이딩 : 부모 클래스의 구현을 자식 클래스에서 새로운 구현으로 대체(자식 클래스의 우선순위가 높음)
메서드 오버로딩 : 부모 클래스에서 정의한 메서드와 이름은 동일하지만 시그니처는 다른 메서드를 자식 클래스에 추가
업캐스팅과 동적 바인딩
업캐스팅 : 부모 클래스 타입으로 선언된 변수에 자식 클래스의 인스턴스를 할당하는 것
다운 캐스팅 : 부모 클래스의 인스턴스를 자식 클래스 타입으로 변환
동적 바인딩(지연 바인딩) : 선언된 변수의 타입이 아니라 메시지를 수신하는 객체의 타입에 따라 실행되는 메서드가 결정(메시지를 처리할 메서드를 런타임에 결정)
정적 바인딩(초기 바인딩, 컴파일 타임 바인딩) : 코드를 작성하는 시점(컴파일타임)에 호출될 메서드가 결정
동적 메서드 탐색과 다형성
객체지향 시스템은 다음 규칙에 따라 실행할 메서드를 선택
1. 메시지를 수신한 객체는 먼저 자신을 생성한 클래스에 적합한 메서드가 존재하는지 검사 -> 존재하면 메서드를 실행하고 탐색을 종료
2. 부모 클래스에서 메서드 탐색 -> 상속 계층을 따라 올라가며 계속됨
3. 상속 계층의 최상위 클래스까지 메서드를 발견하지 못한 경우 -> 예외를 발생시키며 탐색 중단
self 참조
- 객체가 메시지를 수신하면 self 참조라는 임시 변수를 자동으로 생성한 후 메시지를 수신한 객체를 가리키도록 설정
- 동적 메서드 탐색은 self가 가리키는 객체의 클래스에서 시작해서 상속 계층의 역방향으로 이뤄지며 메서드 탐색이 종료되는 순간 소멸됨
동적 메서드 탐색
1. 자동적인 메시지 위임 : 자식 클래스는 자신이 이해할 수 없는 메시지를 전송받은 경우 상속 계층을 따라 부모 클래스에게 처리를 위임
2. 동적인 문맥 사용 : 메시지를 수신했을 때 실제로 어떤 메서드를 실행할지를 결정하는 것은 컴파일 시점이 아닌 실행 시점에 이루어짐 -> self 참조 사용
상속 대 위임
상속은 동적으로 메서드를 탐색하기 위해 현재의 실행 문맥을 가지고 있는 self 참조를 전달
- 객체들 사이에서 메시지를 전달하는 과정은 자동으로 이루어짐(자동적인 메시지 위임)
위임(delegation)
- 자신이 수신한 메시지를 다른 객체에게 동일하게 전달해서 처리를 요청하는 것
- 항상 현재의 실행 문맥을 가리키는 self 참조를 인자로 전달
포워딩(forwarding)
- self 참조를 전달하지 않고 메시지를 전송
프로토타입(prototype) 기반의 객체지향 언어에서 상속을 구현하는 유일한 방법은 객체 사이의 위임을 이용하는 것이다
'책 > Object' 카테고리의 다른 글
일관성 있는 협력 (0) | 2020.09.01 |
---|---|
서브클래싱과 서브타이핑 (0) | 2020.08.25 |
합성과 유연한 설계 (0) | 2020.07.27 |
상속과 코드 재사용 (0) | 2020.07.27 |
유연한 설계 (0) | 2020.07.13 |