List<Dog>은 List<Animal>의 서브클래스인가요? 왜 자바 제네릭은 암시적으로 다형성이 보장되지 않죠?
조회수 1242회
자바 제네릭이 어떻게 상속과 다형성을 다루는지 혼란스럽네요. 아래와 같은 계층구조가 있다고 가정해보겠습니다. Animal(부모) Dog - Cat(자식)
위 상황에 doSomething(List<Animal>
animals) 메소드가 있다고 가정한다면, 상속과 다형성의 법칙에 의거하여, List<Dog>
과 List<Animal>
이 같고 List<Cat>
과 List<Animal>
이 같다고 할 수 있고 List<Dog>
, List<Cat>
각각은 doSomething 메소드를 상속받을 것입니다. 그런데 그렇지 않더군요. 위 가정들을 만족시키려면 메소드에 명시적으로 표시를 해야되더군요. Animal의 어떠한 자식 list를 메소드에서 인자로 받아들이기 위해서 다음과 같이 선언해야만 했어요. doSomething(List<? extends Animal> animals).
이런 부분들이 자바의 원칙이라고 생각되는데요. 제가 궁금하건 왜 그런 것인가 입니다. 자바에서의 다형성은 보통 암시적인데 왜 제네릭에 관해서만 다른거죠?
1 답변
-
아뇨
List<Dog>
과List<Animal>
은 같지 않습니다.List<Animal>
로 무엇을 할 수 있는지 생각해보세요.List<Animal>
에는 어떠한 동물 변수도 추가할 수 있습니다. 물론 cat도 포함해서 말이죠. 논리적으로 새끼강아지 무리에 고양이를 추가할 수 있나요? 절대로 안되죠.// 좋지 않은 코드입니다. List<Dog> dogs = new List<Dog>(); List<Animal> animals = dogs; //잘못된 코드입니다. animals.add(new Cat()); Dog dog = dogs.get(0); // 과연 안전한 코드일까요?
갑작스레 혼잡한 cat이 반환되겠죠. List<? extends Animal>이
List<Cat>
인지 알 수 없기 때문에 List<? extends Animal>에 cat을 추가할 수 없습니다. 리스트에서 값을 찾을 수 있으며 그것이 Animal 이라는 것을 알 수 있을 거예요. 그러나 임의의 animal을 추가할 수는 없죠. 반대의 상황이라면(List<? Super Animal) 리스트에 Animal을 안전하게 추가할 수 있습니다. 그러나 리스트에서 어떤 것이 나올지는 전혀 알 수 없어요. 왜냐면 그 리스트가List<Object>
일 수도 있기 때문이죠..
댓글 입력