■ 다중정의와 호출 예제

다중정의(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에 상속 관계가 복잡해져 위험해 보이는 다중정의를 하게 되더라도 메서드들이 모두 같은 기능을 한다면 문제없다.

 

■ 핵심 정리

  • 매개변수 수가 같을 때는 다중정의를 피하는게 좋다.
  • 헷갈릴만한 매개변수는 형변환하여 정확한 다중정의 메서드가 선택되도록 해야 한다.
  • 기존 클래스를 수정해 새로운 인터페이스를 구현해야 할 때는 같은 객체를 입력받는 다중정의 메서드들이 모두 동일하게 동작하게 만들어야 한다.
  • 네이버 블러그 공유하기
  • 네이버 밴드에 공유하기
  • 페이스북 공유하기
  • 카카오스토리 공유하기