peaches-book-study / effective-java

이펙티브 자바 3/E
0 stars 2 forks source link

Item 52. 다중정의는 신중히 사용하라 #53

Open pyeong114 opened 5 months ago

pyeong114 commented 5 months ago

Chapter : 8. 메서드

Item : 52. 다중정의는 신중히 사용하라

Assignee : pyeong114


🍑 서론

다중정의

: 메서드 오버로딩 : 메서드를 클래스 내에 여러 개 정의할 수 있도록 해주는 기능 : 각 메소드는 매개변수의 타입, 개수, 순서가 달라야 함

🍑 본론

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));
    }
}

"집합","리스트","그 외"가 아닌 "그 외"만 세번 연달아 출력됨!

why? 다중정의된 세 classify 중 어느 메서드를 호출할지가 컴파일타임에 정해지기 때문

컴파일타임에는 for문 안의 c는 항상 Collection<?> 타입이다. 런타임에는 타입이 매번 달라지지만, 호출할 메서드를 선택하는데는 영향을 주지 못한다.

따라서 컴파일 타임의 매개변수 타입을 기준으로 항상 세번째 메서드인 classify(Collection<?>)만 호출하는 것이다.

이처럼 직관과 어긋나는 이유는 재정의한 메서드는 동적으로 선택되고, 다중정의한 메서드는 정적으로 선택되기 때문이다.

// 재정의된 매서드 호출 메커니즘
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.printle(wine.name());
    }
}

위 경우에는 컴파일타임 타입이 모두 Wine인 것에 무관하게 항상 '가장 하위에서 정의한' 재정의 매서드가 실행되는 것이다.

한편, 다중정의된 메서드 사이에서는 객체의 런타임 타입은 전혀 중요치 않다. 선택은 컴파일타임에 오직 매개변수의 컴파일타임 타입에 의해 이뤄진다.

정적 메서드를 사용해도 괜찮다면 이를 이용해서 위의 문제를 해결할 수도 있다

public static String classify(Collection<?> c){
    return c instanceof Set ? "집합" : 
           c instanceof List ? "리스트" : "그 외";
}

다중 정의가 혼동을 일으키는 상황을 피해야 한다. 안전하고 보수적으로 코드를 작성하기 위해선

🍑 결론

프로그래밍 언어가 다중정의를 허용한다고 해서 다중정의를 무조건 활용하란 뜻은 아니다.

일반적으로 매개변수 수가 같을 때는 다중정의를 피하는 게 좋다.


Referenced by

-