본문 바로가기
프로그래밍 놀이터/디자인 패턴, 리펙토링

[Effective Java] 오버로딩(overloading)을 분별력 있게 사용하자.

by 돼지왕왕돼지 2017. 1. 16.

 [Effective Java] 오버로딩(overloading)을 분별력 있게 사용하자.


API, autoboxing, collection, Compile, compile time, Effective JAVA, list, Overload, overloading, overloading method, override, Overriding, Runtime, Set, signiture, static, static factory method, unknown collection, [Effective Java] 오버로딩(overloading)을 분별력 있게 사용하자., 가변 인자, 가변인자, 같은 개수, 같은 매새 변수, 같은 수의 매개변수, 근본적으로 다른 타입, 나쁜 습관, 동적, 매개변수, 메소드, 메소드 이름, 명확성, 보수적, 생성자, 시그니처, 염두, 오버로딩, 정적, 제네릭, 충고, 캐스팅


public class CollectionClassifier{

public static String classify(Set<?> s){

return "Set";

}


public static String classify(List<?> lst){

return "List";

}


public static String classify(Collection<?> c){

return "Unknown Collection";

}


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

}

}

}


위의 코드는 세번 다 Unknown Collection 을 출력한다.
classify 메소드가 오버로딩되어서 호출될 메소드가 컴파일 시점에 결정되기 때문이다.


-
오버로딩된 메소드의 선택은 static인 반면, overriding 된 메소드의 선택은 동적이다.

( overloading 된 메소드의 선택은 compile 타임에, overriding 된 메소드의 선택은 runtime 에. )


-
프로그래머를 혼란 시킬 수 있는 코드를 작성하는 것은 나쁜 습관이다.
API 의 경우 특히 그렇다
만일 주어진 매개 변수들에 대해 오버로딩된 메소드 중 어느 것이 호출될지 API 의 일반 사용자가 모른다면, API 를 사용할 때 에러가 날 가능성이 많다.
그리고 그런 에러들은 런타임시에 불규칙한 행동으로 나타날 것이므로 원인 규명이 힘들 수 있다.
따라서 오버로딩의 혼란스런 사용을 피해야 한다.


-
안전하면서 보수적인 오버로딩 정책은 같은 수의 매개 변수를 갖는 두 개의 오버로딩 메소드를 절대 사용하지 않는 것이다.
만일 어떤 메소드에서 가변인자를 사용한다면 그 메소드는 아예 오버로딩 하지 않는 것이 보수적인 정책.
만일 이런 제약을 고수하면, 어떤 오버로딩 메소드가 어떤 매개변수를 받는지에 대해 프로그래머가 고민할 필요가 없다.
오버라이딩 대신 메소드 이름을 다르게 주는 것이 더 좋다.


-
생성자의 경우 다른 이름을 사용할 수 없다.
그래서 하나의 클래스에는 항상 여러 개의 생성자가 오버로드 되어 있지만, 가능하다면 static 팩토리 메소드를 제공하는 것이 좋다.


-
주어진 실 매개변수에 대해 어떤 오버로딩 메소드가 호출되는지가 항상 분명하면,
같은 개수의 매개변수를 갖는 오버로딩 메소드가 여러 개 있더라도 프로그래머를 혼란스럽게 하지 않는다.
여러 개의 오버로딩 메소드가 갖는 매개 변수 중 최소한 하나가 "근본적으로 다른 타입" 인 경우가 그렇다.
근본적으로 다르다는 것은 각 타입의 인스턴스를 다른 타입으로 캐스팅 할 수 없다는 것을 의미한다.


-
1.5 이후에는 제네릭과 AutoBoxing 이 추가되면서, 오버로딩을 할 때는 추가로 이들을 항상 염두해 두어야 한다.
예를 들어 ArrayList<Integer> 의 경우 remove( E ) 와 remove( int ) 가 명확성을 떨어뜨릴 수 있다.



Summary


메소드를 오버로딩 할 수 있다고 해서 반드시 그렇게 하는 것은 좋지 않다.
같은 개수의 매개 변수를 갖는 메소드 시그니처를 사용해서 메소드를 오버로딩 하는 것은 가급적 삼가야 한다.
하지만 생성자가 오버로딩 되는 경우를 비롯하여 몇몇가지 그런 충고를 따르지 못할 수 있다.
그럴 때는 매개변수 타입의 캐스팅으로 인해 똑같은 집합의 매개 변수들이 서로 다른 오버로딩 메소드로 전달될 수 있는 상황만은 피해야 한다. ( 첫 예제와 같은 상황 )
만일 이런것들이 제대로 되지 못하면, 오버로딩된 메소드나 생성자를 효과적으로 사용해야 할 프로그래머들이 힘들어지며, 에러의 원인규명도 어렵다.





댓글0