■ 다중정의와 호출 예제
다중정의(Overloading)는 어느 메서드가 호출될 지 컴파일 타임에 정해진다.
아래 코드를 실행해보면 직관과 어긋나느 결과를 볼 수 있다.
import java.math.BigInteger;
import java.util.*;
public class CollectionClassifier {
public static String classify(Set<?> s) {
return "집합";
}
public static String classify(List<?> lst) {
return "리스트";
}
public static String classify(Collection<?> c) {
return "그 외";
}
public static void main(String[] args) {
Collection<?>[] collections = {
new HashSet<String>(),
new ArrayList<BigInteger>(),
new HashMap<String, String>().values()
};
for (Collection<?> c : collections)
System.out.println(classify(c));
}
}
런타임에서는 classify의 매개변수인 c의 타입은 변하지만, classify 호출이 Collection<?> c를 매개변수로 받는 메서드가 호출되는 것이 결정되기 때문에, "그 외"만 3번 출력된다.
원래 의도는 매개변수의 런타임 타입에 기초해 적절한 다중정의 메서드로 자동 분배하는 것이었다. 이 문제는 CollectionClassifier의 모든 classify 메서드를 하나로 합친 후 instanceof로 명시적으로 검사하면 해결된다.
public static String classify(Collection<?> c) {
return c instanceof Set ? "집합" :
c instanceof List ? "리스트" : "그 외";
}
■ 다중 정의 사용 시 주의 사항
- API 사용자가 매개변수를 넘기면서 어떤 다중정의가 호출될지를 모른다면 프로그램이 오동작할 수 있으므로 다중정의가 혼동을 일으키는 상황을 피해라
- 안전하고 보수적으로 가려면 매개변수 수가 같은 다중정의는 만들지 말자
- 가변인수를 사용하는 메서드라면 아예 다중정의를 하지 말자
- 다중정의하는 대신 메서드 이름을 다르게 지어주는길도 있다.
■ 생성자
생성자의 경우는 이름을 다르게 지을 수 없다. 하지만 정적 팩터리라는 대안을 활용할 수 있는 경우가 많다.
- 매개변수 중 단 하나라도 근본적(radically different)으로 다르다면 재정의 문제는 일어나지 않는다.
- radically different의 의미는 null이 아닌 두 타입을 어느 한쪽으로 형변환할 수 없음을 의미한다. int를 매개변수로 받는 생성자와 Collection을 받는 생성자는 어느 생성자가 호출될지 컴파일타임에 결정되지 않고, 런타임에 결정된다.
■ 그 외
- 서로 다른 함수형 인터페이스라도 인수 위치가 같으면 헷갈릴 수 있으므로 다중 정의 시 같은 위치의 인수로 받지 말자
- Java 언어의 업그레이드 및 API에 상속 관계가 복잡해져 위험해 보이는 다중정의를 하게 되더라도 메서드들이 모두 같은 기능을 한다면 문제없다.
■ 핵심 정리
- 매개변수 수가 같을 때는 다중정의를 피하는게 좋다.
- 헷갈릴만한 매개변수는 형변환하여 정확한 다중정의 메서드가 선택되도록 해야 한다.
- 기존 클래스를 수정해 새로운 인터페이스를 구현해야 할 때는 같은 객체를 입력받는 다중정의 메서드들이 모두 동일하게 동작하게 만들어야 한다.
'Effective Java' 카테고리의 다른 글
[Effective Java] 아이템54 null이 아닌, 빈 컬렉션이나 배열을 반환하라 (0) | 2021.07.12 |
---|---|
[Effective Java] 아이템53 가변인수는 신중히 사용하라 (0) | 2021.07.12 |
[Effective Java] 아이템51 메서드 시그니처를 신중히 설계하라 (0) | 2021.07.04 |
[Effective Java] 아이템50 적시에 방어적 복사본을 만들라 (0) | 2021.07.04 |
[Effective Java] 아이템49 매개변수가 유효한지 검사하라 (0) | 2021.07.04 |