Skip to content

공변성에 대한 이해 #25

Description

@leejaeseung

언어를 공부할 때마다 공변성에 관한 부분은 항상 나오지만, 쉽지 않은 개념이라 매번 확실히 이해하지 않고 넘겨왔던 것 같습니다.
이번에 팀 내부 스터디에서 공변성 관련 내용이 나왔는데 드디어 어느정도 이해를 한 것 같아 내용을 공유드리려 합니다.

저희 팀 테크 리더께서 공변성 관련 링크를 주셔서 대충이나마 번역해 보았습니다.
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
  1. 읽기 - 위 할당에 따르면, List foo3 로부터 읽을 수 있는 객체 :
    • Number 를 읽을 수 있다. foo3 에 할당될 수 있는 목록에는 NumberNumber 의 하위 클래스가 포함되어 있기 때문이다.
    • Integer 는 읽을 수 없다. foo3List<Double> 타입일 수도 있기 때문이다.
    • Double 는 읽을 수 없다. foo3List<Integer> 타입일 수도 있기 때문이다.
  2. 쓰기 - 위 할당에 따르면, 위의 모든 List foo3 에 추가할 수 있는 객체 :
    • Integer 를 추가할 수 없다. foo3List<Double> 타입일 수도 있기 때문이다.
    • Double 를 추가할 수 없다. foo3List<Integer> 타입일 수도 있기 때문이다.
    • Number 를 추가할 수 없다. foo3List<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
  1. 읽기 - 위 할당에 따르면, List foo3 로부터 읽을 수 있는 객체 :
    • Integer 를 읽을 수 없다. foo3List<Number>List<Object> 타입일 수 있기 때문이다.
    • Number 를 읽을 수 없다. foo3List<Object> 타입일 수 있기 때문이다.
    • 오로지 보장받을 수 있는 건 ObjectObject 의 서브클래스일 거라는 것 뿐이다. (어떤 서브클래스인진 모르겠지만)
  2. 쓰기 - 위 할당에 따르면, 위의 모든 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 임이 보장.
  • 스칼라의 -

공변성에 대해 저는 아래 그림처럼 이해하였습니다.

image

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions