Skip to content

Latest commit

 

History

History
137 lines (106 loc) · 3.34 KB

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

File metadata and controls

137 lines (106 loc) · 3.34 KB

부제 : 매개변수의 수가 같은 다중정의는 피하자.

class Human {

}

class Girl extends Human {

}

class Boy extends Human {

}
public class Main {
    public static void print(Girl girl) {
        System.out.println("여자여자");
    }

    public static void print(Boy boy) {
        System.out.println("남자남자");
    }

    public static void print(Human human) {
        System.out.println("인간인간");
    }

    public static void main(String[] args){
        List<? extends Human> people = new ArrayList<>(List.of(new Human(), new Boy(), new Girl()));
        for (Human person : people) {
            print(person);
        }
    }
}

  • 일반적으로 인간인간, 남자남자, 여자여자가 나올 것으로 추측
  • 실제 출력은 인간인간만 3번 출력
  • 세개의 print 메소드중 어느 메서드를 호출할 지는 컴파일 타임에 정해진다.
  • 런타임의 경우에는 타입이 달라진다. → 실제 인스턴스의 타입
  • 컴파일 타임에 print(person)에서 person은 Human 타입이다.
  • 재정의한 메소드는 동적으로 선택되고, 다중정의한 메소드는 정적으로 선택된다.
  • 다중정의된 메서드에서는 객체의 런타임 타입이 무엇인지는 신경쓰지 않는다.

재정의


class Human {
    public void print() {
        System.out.println("인간인간");
    }
}

class Girl extends Human {
    @Override
    public void print() {
        System.out.println("여자여자");
    }
}

class Boy extends Human {
    @Override
    public void print() {
        System.out.println("남자남자");
    }
}

public class Main {
    public static void main(String[] args){
        List<? extends Human> people = new ArrayList<>(List.of(new Human(), new Boy(), new Girl()));
        for (Human person : people) {
            person.print();
        }
    }
}
  • 컴파일타임 타입이 Human인것과 무관하게 가장 하위에서 정의한 재정의 메서드 실행

해결 방안


public class Main {
    public static void print(Human human) {
        if (human instanceof Girl) {
            System.out.println("여자여자");
            return;
        }
        if (human instanceof Boy) {
            System.out.println("남자남자");
            return;
        }
        if (human instanceof Human) {
            System.out.println("인간인간");
        }
    }

    public static void main(String[] args){
        List<? extends Human> people = new ArrayList<>(List.of(new Human(), new Boy(), new Girl()));
        for (Human person : people) {
            print(person);
        }
    }
}
  • 모든 메소드를 통합한 다음 instanceof로 명시적으로 클래스 검사 진행

즐거운 예시


List<Integer> list = new ArrayList<>();
list.addAll(List.of(1, 2, 3, 4, 5));

list.remove(3); // 3번째 인덱스 제거
list.remove((Integer)3); // 숫자 3 제거

결론


  • 다중정의가 혼동을 일으키는 상황을 피해야 한다.
  • 안전하고 보수적으로 가려면 매개변수 수가 같은 다중정의는 만들지 말자.
    • 다중정의하는 대신 메서드 이름을 다르게 지어줄 수도 있다.
  • 헷갈릴 만한 매개변수는 형변환하여 정확한 다중정의 메소드가 선택되도록 해야 한다.