부모 타입에 자식 타입을 참조시킬 수 없다.
List<Animals> animals = ArrayList<Dog>();
은 불가능하다.
다형성을 이용해 참조시킬 수 있을까?
Dog은 Animal의 자손 타입이니 가능하지 않을까?
1 |
|
- 해당 코드가 컴파일이 될거 같은가?
- 결론부터 이야기하면 컴파일 에러가 발생한다.
- 자바 제너릭을 처음 배울때, 보통 책에서는 타입변수와 실제타입이 일치해야만 생성이 가능하다고 설명해둔다.
- 그냥 그대로 받아들이고 넘어갈 수 도 있지만,
- 왜 그런거지? 자손타입이면 가능해야 하는게 아닌가? 라는 생각을 한번 해볼 수 있지 않을까?
왜 안돼?
그러면 Animal List에는 Dog을 넣을수 없다는거야?
1 |
|
- 그렇다면 해당 코드도 안되는건가?
- 이것은 된다.
아 그러면 생성때만 안되는건가?
Animal을 미리 만들어두고, Dog를 참조 시켜볼까?
1 |
|
- 역시나 안된다.
개들의 집합은 동물들의 집합이지 않은가?
하위집단으로는 가능하나, 참조가 될순 없다.
- 만약 Cat 이라는 Animal의 자손 클래스가 하나 더 있다고 생각해보자.
1 |
|
- 만약 위에서 본 이 상황이 컴파일이 된다면?
- animal List에 Dog들이 들어가는것이 아닌, animal List가 Dog List으로 만들어진다는 것이다.
1 |
|
- 그렇다면 이
Cat
은 어떻게 되는가? - Cat이 의도했던것은 animals의 집합에 속하는것이다.
- 하지만 지금 animals는 Dog의 집합이 되어있다.
- 그렇다면 고양이는 개가 되는것인가? 말이 안되는 소리이다.
그렇다면 어떻게 고양이와 개를 넣을래?
1 |
|
- 다음과 같이 하면된다.
메소드로 분리하는 방법
1 |
|
- 이글을 쓰게된 주 원인중 하나이다.
- 이제 왜 인자로 dogs을 넣을수 없는지를 알수 있을 것이다.
1 |
|
- 메소드로 분리하고 싶다면, 와일드 카드를 이용해
method(List<? extends Animal> animal)
매개변수로 넘겨줄 수 있다. - 참조형으로 다형성을 이용할 수 없는것이지, 해당 타입을 다형성으로 소화하지 못한다는 이야기가 아니기 때문이다.
자동으로 처리해주는것의 이유를 생각해보자
1 |
|
- 인텔리제이에서 첫번째 라인처럼 쓰면 안의
Dog
을 굳이 써주지 않아도 된다고 이야기해준다. - 아래처럼 쓰면 암시적으로 저안에 Dog을 넣어주기 때문이다.
- 그 이유는 제너릭 타입으로 들어갈 수 있는것은 Dog 단 하나이기 때문이다!
Reference
- https://stackoverflow.com/questions/5763750/why-we-cant-do-listparent-mylist-arraylistchild?noredirect=1&lq=1
- https://stackoverflow.com/questions/2745265/is-listdog-a-subclass-of-listanimal-why-are-java-generics-not-implicitly-po