다형성에 대한 내용이다
자세한 내용이 궁금하면 오브젝트를 펼쳐보는 걸 추천드립니다.📖
시작하면서
객체지향 패러다임이 주목받기 시작한 초기에 상속은 계층 타입과 다형성을 구현하는 유일한 방법이었고, 상속을 이용하면 코드를 재사용할 수 있다는 '과대광고'가 널리 생겨 상속에 대한 맹신과 추종이 생겼다. 현재는 다양한 방법으로 다형성을 구현할 수 있어서 상속의 비중은 많이 사라졌다.
다형성(Polymorphism)
다형성은 많은 형태를 가질 수 있는 능력을 의미하며, 객체지향 프로그래밍에서 다형성은 다양하게 존재한다.
하나의 클래스안에 동일한 이름의 메서드가 존재하면 오버로딩 다형성이라 한다.
public class Money {
// 오버로딩
public Money plus(Money amount) {...};
public Money plus(BigDecimal amount) {...};
public Money plus(long amount) {...};
}
강제 다형성은 동일한 연산자를 다양한 타입에 사용할 수 있는 방식을 가리킨다. 자바의 이항 연산자 '+' 를 생각하라
int amount = 10 + 10; // 덧셈 연산자
String text = 1000 + "원"; // 연결 연산자
매개변수 다형성은 제네릭 프로그래밍과 관련이 있는데 임의의 타입을 사용하는 시점에 구체적인 타입으로 지정하는 방식이다.
자바의 List 인터페이스를 생각하라
포함 다형성은 메시지가 동일하더라도 수신한 객체의 타입에 따라 실제로 수행되는 행동이 달라진다. 다른 말로 서브타입 다형성이라 부른다. 다형성이라 하면 대부분 포함 다형성을 의미 한다. 흔히 상속을 사용한다.
상속의 양면성
상속이란 부모 클래스에서 정의한 데이터와 행동을 자식클래스에게 자동 적으로 공유할 수 있는 재사용 메커니즘으로 보일 수 있지만, 이 관점은 상속을 오해한 것이다.
상속의 목적은 코드 재사용이 아니라 다형성을 가능하게 하는 '타입 계층'을 구축하기 위한 것이다
데이터 관점의 상속
데이터 관점의 상속은 자식 클래스의 인스턴스 안에 부모 클래스의 인스턴스를 포함하는 것으로 본다.
행동 관점의 상속
행동 관점의 상속은 부모 클래스의 메서드 일부를 자식 클래스의 메서드로 포함시키는 것을 의미한다.
실제로 코드를 합치는건 아니고 런타임이 자식 클래스만 탐색하지 않고 부모 클래스까지 함께 탐색한다.
업캐스팅
업캐스팅은 부모 클래스 타입으로 선언된 변수에 자식 클래스의 인스턴스를 할당하는 것이다.
Lecture parent = new GradeLecture();
반대로 부모 클래스의 인스턴스를 자식 클래스 타입으로 변환하는 것을 다운 캐스팅이라고 한다.
Lecture parent = new GradeLecture();
GradeLecture child = (GradeLecture)parent;
동적 바인딩
동적 바인딩은 메시지를 수신하는 객체에 타입에 따라 실행되는 메서드가 결정되는 것을 의미한다. 다른 용어로 지연 바인딩이라고 부른다.
동적 메서드 탐색과 다형성
객체가 메시지를 수신하면 컴파일러는 self 참조(self reference)라는 임시 변수를 생성하여 메시지를 수신한 객체를 가리키도록 설정한다. 그리고 객체지향 시스템은 규칙에 따라 실행할 메시지를 탐색하여 선택한다.
- 메시지를 수신한 객체는 자신을 생성한 클래스에 적합한 메서드가 존재하는 검사 한다. 존재하면 실행하고 탐색을 종료한다.
- 찾지 못했으면 부모 클래스로 찾아가 탐색을 한다. 못 찾으면 계속 상속 계층을 타고 올라간다.
- 최상위 계층까지 찾지 못했으면 예외를 발생하고 중단한다.
* 같은 이름의 메서드가 자식과 부모 모두에 존재한다면 탐색은 자식부터 시작하기에 자식 메서드에 우선순위가 있다.
동적 메서드 탐색은 두 가지로 원리를 가진다
- 자동적인 메시지 위임 : 자식 클래스에서 부모 클래스까지 상속 계층을 따라 처리를 위임
- 동적인 문맥 : 어떤 메서드를 실행할지는 컴파일시점이 아니라 실행시점에 이뤄지며, self 참조를 이용해 결정
super 참조(super reference)
자식 클래스에서 부모 클래스의 구현을 재사용하는 경우가 있는데, 이를 위해 super 참조라는 내부 변수를 제공한다.
class Lecture {
public void run() {
System.out.println("부모");
}
}
class GradeLecture extends Lecture {
public void run2() {
super.run();
}
}
자식인 GradeLecture는 super 참조를 이용해 부모 클래스에게 메시지를 '전송'한다. 많은 오해가 있는데 super 참조로 메서드를 호출하는 건 아니다. 더 상위에 존재하는 부모일 수 있다.
마치 부모 클래스에게 메시지를 전송하는 것처럼 보여 super 전송이라 부르기도 한다.
'서적 > 오브젝트: 코드로 이해하는 객체지향 설계' 카테고리의 다른 글
오브젝트 14_ 일관성 있는 협력 (0) | 2021.06.10 |
---|---|
오브젝트 13_ 서브클래싱과 서브타이핑 (0) | 2021.06.10 |
오브젝트 11_ 합성과 유연한 설계 (0) | 2021.06.10 |
오브젝트 10_ 상속과 코드 재사용 (0) | 2021.06.09 |
오브젝트 09_ 유연한 설계 (0) | 2021.06.09 |