Skip to content

Files

55 lines (42 loc) · 2.66 KB

다중정의는_신중히_사용하라.md

File metadata and controls

55 lines (42 loc) · 2.66 KB

다중정의는 신중히 사용하라

프로그래머가 기대한 대로 동작하지 않는다

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 Collection<?>[] {  
                new HashSet<String>(),  
                new ArrayList<BigInteger>(),  
                new HashMap<String, String>().values()  
        };  
  
        for (Collection<?> c : collections) {  
            System.out.println(classify(c));  
        }
    }  
}
  • "집합", "리스트", "그 외"를 차례로 출력할 것 같지만, 실제로 수행해보면 "그 외"만 세 번 연달아 출력한다.
  • 직관이 어긋나는 이유는 재정의한 메서드는 동적으로, 다중정의한 메서드는 정적으로 선택되기 때문이다.
    • 다중정의된 메서드 선택은 컴파일타임에, 오직 매개변수의 컴파일타임 타입에 의해 이뤄진다.

다중정의가 혼동을 일으키는 상황을 피해야 한다.

어떻게 사용했을 때 다중정의가 혼란을 줄까?

  • 매개변수 수가 같을 때
  • 가변인수를 사용할 때

  1. 다중정의하는 대신 메서드 이름을 다르게 지어주는 길도 있다.
  2. 생성자는 이름을 다르게 지을 수 없으니 두 번째부터는 무조건 다중정의된다. 하지만 정적 팩터리라는 대안을 활용할 수 있는 경우가 많다.
  3. 매개변수 중 하나 이상이 "근본적으로 다르다"면 헷갈릴 일이 없다.
  • 근본적으로 다르다는 건 두 타입의 (null이 아닌) 값을 서로 어느 쪽으로든 형변환할 수 없다는 뜻이다.
  • 오토박싱, 제네릭, 람다와 메서드 참조가 다중정의 시의 혼란을 키웠다.
    • 메서드를 다중정의할 때, 서로 다른 함수형 인터페이스라도 같은 위치의 인수로 받아서는 안 된다.
  1. 다중정의된 메서드 중 하나를 선택하는 규칙은 매우 복잡하며, 자바가 버전업될수록 더 복잡해지고 있어, 이 모두를 이해하고 사용하는 프로그래머는 극히 드물 것이다. 어떤 다중정의 메서드가 불리는지 몰라도 기능이 똑같다면 신경 쓸 게 없다.
  • 이렇게 하는 가장 일반적인 방법은 상대적으로 더 특수한 다중정의 메서드에서 덜 특수한 다중정의 메서드로 일을 넘겨버리는 것이다.