[이펙티브자바] 52강. overloading은 신중히 사용하라

serious_yeon·2023년 3월 26일
0

책읽자

목록 보기
3/3
post-custom-banner
- overloading
- compile time
- 문제상황
- 해결책

오버로딩

  • overriding (재정의)
    부모의 메소드를 재정의한다.
    런타임에 선택된다.
  • overloading (다중정의)
    이름은 같지만 매개변수 유형이 다르거나, 이름은 같지만 매개변수 개수가 다른 메소드이다. 매개변수 개수가 같은 경우 어떤 메소드가 호출될지 헷갈린다.
    컴파일 타임에 선택된다.

컴파일타임

  • 컴파일타임
    소스코드를 기계어로 번역하는 과정
    컴파일 오류는 ; 누락, 괄호 누락 등이 있다. ide의 도움으로 발견하기 쉽다
  • 런타임
    실행 과정
    런타임 오류는 NullPointException, InfiniteLoop 등이 있다. 에러 발생 시 역추적해야 한다

문제상황

  • 오버로딩한 메서드는 헷갈리기 쉽다.
  • 원인
    컴파일 타임에 호출될 메서드가 정해진다.
    특히 매개변수 개수가 같다면 더 헷갈린다.
  • 해결책
    매개변수 개수가 같으면 오버로딩을 지양한다.
    오버라이딩을 쓴다.
    런타임에 호출할 메서드가 특정되도록 코드를 작성한다.
    추가 메서드를 정의하고, 이름을 다르게 짓는다.
    매개변수 개수가 같다면, 유형이 확실하게 다르도록 코드를 작성한다.
public class CollectionClassifier {
	public static String classify(Set<?> s) {
    	return "집합";
    }
    
    public static String classify(Set<?> s) {
    	return "리스트";
    }
    
    public static String classify(Set<?> s) {
    	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.our.println(classify(c));
    }
}
  • 오버라이딩을 쓴다.
public class Overriding{
	public static void main(String[] args) {
    	List<Wine> wineList = List.of(
        	new Wine(), new SparkingWine(), new Champagne());
            
        for (Wine wine : wineList)
        	System.out.println(wine.name());
    }
}
  • 런타임에 호출할 메서드가 특정되도록 코드를 작성한다.
public static String classify(Collection<?> c) {
	return c instanceof Set ? "집합" :
    		c instanceof List ? "리스트" : "그 외";
}
  • 헷갈리지 않도록 추가 메서드를 정의하고, 이거는 이름을 다르게 짓는다.
ObjectOutputStream의 
writeBoolean, writeInt, writeLong
readBoolean, readInt, readLong

// 생성자는 같지만 추가 메소드 덕분에 헷갈리지 않는다
  • 매개변수 개수가 같다면, 유형이 확실하게 다르도록 코드를 작성한다.
    Object와 int는 형변환 가능하다. 그러므로 헷갈리기 쉽다.
    String과 Throwable은 다르다.
public class SetList {
	public static void main(String[] args) {
    	Set<Integer> set = new TreeSet<>();
        List<Integer> list = new ArrayList<>();
        
        for (int i=-3; i<3; i++) {
        	set.add(i);
            list.add(i);
        }
        
        // 잘못된 예. index와 헷갈린다
        for (int i=0; i<3; i++) {
        	set.remove(i);
            list.remove(i);
        }
        
        // 올바른 예
        for (int i=0; i<3; i++) {
        	set.remove(i);
            list.remove((Integer) i);
        }
        
        System.out.println(set + " " + list);
    }
}
post-custom-banner

0개의 댓글