-
Notifications
You must be signed in to change notification settings - Fork 0
Open
Description
언어를 공부할 때마다 공변성에 관한 부분은 항상 나오지만, 쉽지 않은 개념이라 매번 확실히 이해하지 않고 넘겨왔던 것 같습니다.
이번에 팀 내부 스터디에서 공변성 관련 내용이 나왔는데 드디어 어느정도 이해를 한 것 같아 내용을 공유드리려 합니다.
저희 팀 테크 리더께서 공변성 관련 링크를 주셔서 대충이나마 번역해 보았습니다.
Difference between <? super T> and <? extends T> in Java [duplicate]
자바에서 <? super T> 와 <? extends T> 의 차이점
List<? extends T> 를 사용하면 list.add(e) 가 불가능하다. (요소 추가가 불가)
하지만 List<? super T> 에선 가능하다
extends
와일드카드 정의인 List<? extends Number> foo3 는 아래 모든 할당이 가능하다는 뜻이다.
List<? extends Number> foo3 = new ArrayList<Number>();
// Number "extends" Number (in this context)
List<? extends Number> foo3 = new ArrayList<Integer>();
// Integer extends Number
List<? extends Number> foo3 = new ArrayList<Double>();
// Double extends Number- 읽기 - 위 할당에 따르면,
List foo3로부터 읽을 수 있는 객체 :Number를 읽을 수 있다.foo3에 할당될 수 있는 목록에는Number나Number의 하위 클래스가 포함되어 있기 때문이다.Integer는 읽을 수 없다.foo3가List<Double>타입일 수도 있기 때문이다.Double는 읽을 수 없다.foo3가List<Integer>타입일 수도 있기 때문이다.
- 쓰기 - 위 할당에 따르면, 위의 모든
List foo3에 추가할 수 있는 객체 :Integer를 추가할 수 없다.foo3가List<Double>타입일 수도 있기 때문이다.Double를 추가할 수 없다.foo3가List<Integer>타입일 수도 있기 때문이다.Number를 추가할 수 없다.foo3가List<Integer>타입일 수도 있기 때문이다.
List 가 어떤 타입일 지 알 수 없으므로 List<? extends T> 에 어떤 객체도 추가할 수 없다. 타입을 보장받을 수 있는 건 읽을 때 T 혹은 T 의 서브 클래스라는 것 뿐이다.
super
이제 List <? super T> 를 보자.
와일드카드 정의인 List<? super Integer> foo3 는 아래 모든 할당이 가능하다는 뜻이다.
List<? super Integer> foo3 = new ArrayList<Integer>();
// Integer is a "superclass" of Integer (in this context)
List<? super Integer> foo3 = new ArrayList<Number>();
// Number is a superclass of Integer
List<? super Integer> foo3 = new ArrayList<Object>();
// Object is a superclass of Integer
- 읽기 - 위 할당에 따르면,
List foo3로부터 읽을 수 있는 객체 :Integer를 읽을 수 없다.foo3가List<Number>나List<Object>타입일 수 있기 때문이다.Number를 읽을 수 없다.foo3가List<Object>타입일 수 있기 때문이다.- 오로지 보장받을 수 있는 건
Object나Object의 서브클래스일 거라는 것 뿐이다. (어떤 서브클래스인진 모르겠지만)
- 쓰기 - 위 할당에 따르면, 위의 모든
List foo3에 추가할 수 있는 객체 :Integer를 추가할 수 있다.Integer는 모든 list 들이 포함하고 있기 때문이다.Integer의 서브클래스도 마찬가지이다.Double,Number,Object는 추가할 수 없다.ArrayList<Integer>타입일 수 있기 때문이다.
PECS
Remember PECS: "Producer Extends, Consumer Super".
- "Producer Extends" -
T값을 produce 하는List가 필요하다면(==T값을 리스트로부터 읽고 싶다면)? extends T로 선언해야 한다. 하지만 이 리스트에 값을 추가할 순 없다. - "Consumer Super" -
T값을 consume 하는List가 필요하다면(==T값을 리스트에 넣고 싶다면)? super T로 선언해야 한다. 하지만 이 리스트로부터 어떤 타입을 읽을지는 보장받을 수 없다. - 읽기와 쓰기를 모두 하고 싶다면, 정확한 타입을 정의해야 한다.
Extends vs Super 에 대해 이해한 내용
<? extends T>
- ? 의 타입이 최대 T 타입인 걸 보장한다.
- 읽기 가능
- 공변
- 코틀린의 out : 출력값이 T. 즉, out 하는 값이 최소 T 임이 보장.
- 스칼라의 +
<? super T>
- ? 의 타입이 최소 T 타입인 걸 보장한다.
- 쓰기 가능
- 반공변
- 코틀린의 in : 입력값이 T. 즉, in 하는 값이 최대 T 임이 보장.
- 스칼라의 -
공변성에 대해 저는 아래 그림처럼 이해하였습니다.
Metadata
Metadata
Assignees
Labels
No labels
