다중 정의가 무엇이냐
자바 기초를 공부하신 분이면 다들 알고 계시는 오버로딩(overloading)입니당
"같은 이름의 메소드를 중복하여 정의하는 것을 의미"
자바는 한 클래스 내에 같은 이름의 메소드가 둘 이상있어도
매개변수의 개수나 타입을 다르게 하면, 하나의 이름으로 메소드를 작성이 가능하다.
즉, 앞에서 배운 서로 다른 시그니처를 갖는 여러 메소드를 같은 이름으로 정의하는 것이라고 할 수 있다.
그럼 왜 다중정의는 신중해야할까
다중 정의 메서드는 개발자가 기대한 것처럼 동작하지 않는 경우가 있기 때문!
52-1) 컬렉션 분류기
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(CollectionClassifier.classify(c));
}
}
}
//그 외
//그 외
//그 외
결과적으로 '그 외'만 세번 출력됐는데,
다중정의된 세 classify 중 어느 메서드를 호출할지가 컴파일타임에 정해지기 때문이다.
컴파일타임에는 for문 안의 변수 c는 Collection<?> 타입이다.
"런타임에는 타입이 매번 달라지지만, 호출할 메서드를 선택하는 데는 영향을 주지 못한다.
따라서 컴파일타임의 매개변수 타입을 기준으로 항상 세 번째 메서드인 classify(Collection<?>)만 호출하는 것이다."
위의 예시처럼 직관에 어긋나는 이유는
재정의한 메서드는 동적으로 선택되고, 다중정의(overloading)한 메서드는 정적으로 선택되기 때문이다.
메서드를 재정의(override) 했다면 해당 객체의 런타임 타입이 어떤 메서드를 호출할지의 기준이 된다.
52-2)재정의된 메서드 호출 메커니즘
class Wine {
String name(){
return "포도주";
}
}
class SparklingWine extends Wine{
@Override
String name(){
return "발포성 포도주";
}
}
class Champagne extends SparklingWine{
@Override
String name(){
return "샴페인";
}
}
public class Overriding{
public static void main(String[] args) {
List<Wine> wineList = List.of(new Wine(), new SparklingWine(), new Champagne());
for(Wine wine : wineList){
System.out.println(" 🍇 " +wine.name());
}
}
}
//🍇 포도주
//🍇 발포성 포도주
//🍇 샴페인
포도주, 발포성 포도주, 샴페인이 차례로 출력됐는데,
for 문에서의 컴파일타임 타입이 모두 Wine인 것에 무관하게 항상 '가장 하위에서 정의한 ' 재정의 메서드가 실행된 것이다.
"다중정의된 메서드 사이에서는 객체의 런타임 타입은 전혀 중요치 않다.
선택은 컴파일타임에, 오직 매개변수의 컴파일타임 타입에 의해 이뤄진다."
52-1의 CollectionClassifier 클래스도 52-2 Wine 클래스처럼
런타임 타입에 기초해 적절한 다중정의 메서드로 자동 분배하고 싶으면 다음과 같이 바꿀 수 있다.
public static String classify(Collection<?> c){
return c instanceof Set ? "집합" : c instanceof List ? "리스트" : "그 외";
}
즉, 하고 싶은 말은
52-1 CollectionClassifier 클래스처럼 프로그래머가 기대한 대로(집합, 리스트, 그외가 차례로 출력되는...)
동작하지 않을 수 있으니 다중정의로 혼동을 일으키는 상황을 피하자라는 것이다.
더불어 가변인수를 사용하는 메서드는 다중정의는 더더욱 피해야한다.
'🤓 스터디 > 이펙티브 자바' 카테고리의 다른 글
[아이템 54] null이 아닌, 빈 컬렉션이나 배열을 반환하라 (0) | 2023.04.19 |
---|---|
[아이템 53] 가변인수는 신중히 사용하라 (0) | 2023.04.18 |
[아이템 51] 메서드 시그니처를 신중히 설계하라 (0) | 2023.04.17 |
[아이템 50] 적시에 방어적 복사본을 만들라 (0) | 2023.04.17 |
[아이템 49] 매개변수가 유효한지 검사하라 (0) | 2023.04.13 |
댓글