생각해보기
오브젝트(조영호) 책 정리 -12- 본문
다형성은 여러 타입을 대상을 동작할 수 있는 코드를 작성할 수 있는 방법이다.
다형성의 종류
- 유니버설 다형성
- 매개 변수 다형성 : 제네릭 프로그래밍과 같이 클래스의 인스턴스 변수나 매서드의 매개변수 타입을 임의의 타입을 선언한 후 사용하는 시점에 구체적인 타입으로 지정하는 방식
- 포함 다형성 : 메시지가 동알하더라도 수신한 객체의 타입에 따라 실제로 수행하는 행동이 달라지는 것
- 임시 다형성
- 오버로딩 다형성 : 하나의 클래스 안에 동일한 이름의 메서드가 존재하는 경우
- 강제 다형성 : 언어가 지원하는 자동적인 타입 변환이나 이항 연산자 '+'와 같이 정수에는 덧셈, 문자열에는 연결 연산자처럼 작동하게 하는 것
상속의 목적은 코드의 재사용이 아니다. 상속은 프로그램을 구성하는 개념들을 기반으로 다형성을 가능하게 하는 타입 계층을 구축하기 위한 것이다.
객체의 경우에는 서로 다른 상태를 저장할 수 있도록 각 인스턴스별로 독립적인 메모리를 할당받아야 한다. 하지만 메서드의 경우에는 동일한 클래스의 인스턴스끼리 공유가 가능하기 때문에 클래스는 한 번만 메모리에 로드하고 각 인스턴스 별로 클래스를 가르키는 포인터를 갖게 한다.
기본 클래스의 예시
메시지를 수신한 객체는 class 포인터로 연결된 자신의 클래스에서 적절한 메서드가 존재하는지를 찾는다. 만약 존재하지 않는다면 부모 클래스, 인터페이스 순으로 찾는다.
private PublicMethods.MethodList getMethodsRecursive(String name,
Class<?>[] parameterTypes,
boolean includeStatic) {
// 1st check declared public methods
Method[] methods = privateGetDeclaredMethods(/* publicOnly */ true);
PublicMethods.MethodList res = PublicMethods.MethodList
.filter(methods, name, parameterTypes, includeStatic);
// if there is at least one match among declared methods, we need not
// search any further as such match surely overrides matching methods
// declared in superclass(es) or interface(s).
if (res != null) {
return res;
}
// if there was no match among declared methods,
// we must consult the superclass (if any) recursively...
Class<?> sc = getSuperclass();
if (sc != null) {
res = sc.getMethodsRecursive(name, parameterTypes, includeStatic);
}
// ...and coalesce the superclass methods with methods obtained
// from directly implemented interfaces excluding static methods...
for (Class<?> intf : getInterfaces(/* cloneArray */ false)) {
res = PublicMethods.MethodList.merge(
res, intf.getMethodsRecursive(name, parameterTypes,
/* includeStatic */ false));
}
return res;
}
자식 클래스에서 부모 클래스로의 메소드 탐색이 가능하기 때문에 자식 클래스는 마치 부모 클래스에 구현된 메소드의 복사본을 가지고 있는 것처럼 보인다. 따라서 각 객체에 포한된 clsss 포인터와 클래스에 포함된 parent 포인터를 조합하면 현재 인스턴스의 클래스에서 최상위 부모 클래스까지 모든 부모 클래스에 접근이 가능하다
상속 클래스 예시
* 메소드 오버라이딩과 오버로딩
메서드 오버라이딩 : 자식 클래스 안에 상속받은 메서드와 동일한 시그니처의 메서드를 재정의 해서 부모 클래스의 구현을 새로운 구현으로 대체하는 것
메소드 오버로딩 : 부모 클래스에서 정의한 메서드와 이름은 동일하지만 시그니처는 다른 메서드를 자식클래스에 추가하는 것
* 동적 바인딩, self 참조, super 참조
동적 바인딩, self 참조 : 동일한 메세지를 수신하더라도 객체의 타입에 따라 적합한 메서드를 동적으로 선택할 수 있다
super 참조 : 부모 클래스의 코드를 접근할 수 있게 함으로써 중복 코드를 제거 할 수 있다.
*포워딩과 위임
포워딩 : 처리를 요청할 때 self 참조를 전달하지 않는 경우 (다른 객체에게 요청을 처리할 때 self를 전달하지 않고 싶을 때, 요청을 전달받은 최초의 객체에 다시 메시지를 전송할 필요 없이 단순히 코드를 재사용하고 싶을 때 사용)
위임 : self 참조를 전달하는 경우(클래스를 이용한 상속 관계를 합성 관계로 대체해서 다형성을 구현할 때 사용)
'객체지향' 카테고리의 다른 글
오브젝트(조영호) 책 정리 -14- (0) | 2021.12.03 |
---|---|
오브젝트(조영호) 책 정리 -13- (0) | 2021.12.02 |
오브젝트(조영호) 책 정리 -11- (0) | 2021.11.23 |
오브젝트(조영호) 책 정리 -10- (0) | 2021.11.22 |
오브젝트(조영호) 책 정리 -9- (0) | 2021.11.21 |