본문 바로가기
자바

자바의 변성 - 공변/무공변/반공변, 사용지점 변성과 선언 지점 변성

by 책 읽는 개발자_테드 2022. 2. 8.
반응형

목차

· 변성

· 제네릭과 공변/무공변

· 와일드카드 타입과 공변/반공변

· 사용지점 변성과 선언 지점 변성


변성


변성(Variance)은 타입의 계층 관계에서 서로 다른 타입 간에 어떤 관계가 있는지 나타내는 개념이다.

해당 개념은 자바의 제네릭을 설명하기 위해 자주 사용된다. 

 

변성에는 네 가지 종류가 있다.

공변(covariant), 반공변(contravariant), 이변량(bivariant), 무공변(or 불공변, invariant)

이 중에서 알아볼 것은 공변, 반공변, 무공변이다.

 

제네릭과 공변/무공변


공변은 사전적 의미로 '함께 변하는'이라는 뜻이다.

 

 

제네릭은 기본적으로 무공변(or 불공변, invariant)이다.

즉, 서로 다른 타입 Type1과 Type2가 있을 때, List<Type1>은 List<Type2>의 하위 타입도 아니고 상위 타입도 아니라는 뜻이다.

 

이와 반대로 배열은 공변이다. 

즉, Sub 타입이 Super 타입의 하위 타입이라면, 배열 Sub[]은 배열 Super[]의 하위 타입이다.

 

와일드카드 타입과 공변/반공변


하지만 제네릭이 이렇게만 사용되면, 제네릭의 표현은 너무 한정적이게 된다.

따라서 제네릭에는 '한정적 와일드카드 타입'이라는 기능이 제공된다.

 

타입 매개변수에 <? extends Type>를 선언하면 타입 매개변수에 공변이 선언될 수 있다. 

즉, 아래코드에 src 매개변수에는 'E의 하위 타입의 Iterable'만 입력될 수 있다.

 

public void pushAll(Iterable<? extends E> src) {
    for( E e : src )
        push(e);
}

 

반대로, 타입 매개변수에 <? super Type>를 선언하면 타입 매개변수에 반공변(contravariance)이 선언될 수 있다.

즉, 아래코드에 src 매개변수에는 'E 상위 타입의 Iterable'만 입력될 수 있다.

public void pushAll(Iterable<? super E> src) {
    for( E e : src )
        push(e);
}

 

사용지점변성과 선언지점변성


앞서 살펴본대로 자바에는 한정적 와일드카드 타입을 통해 타입의 공변성 또는 반공변성을 지정할 수 있다.

이렇게 타입 파라미터가 나타나는 지점에 변성을 정하는 자바의 방식을 사용지점변성(use-site variance)이라 한다.

 

어떠한 타입 T의 공변성을 허용하려면 <? extend T>를 사용한다.
어떠한 타입 T의 반공변성을 허용하려면 <? super T>를 사용한다.

 

자바와 같이 JVM을 이용하는 언어인 코틀린에서도 사용자 지점 변성을 제공한다.

 

코틀린에서는 사용 지점 변성을 out과 in 키워드를 이용해 지원한다.
자바의 <? extend T>가 코틀린에서는 <out T>이다.
자바의 <? super T>가 코틀린에서는 <in T>이다.

 

여기에 추가적으로 선언지점변성을 제공한다. 선언 지점 변성은 클래스를 선언할 때 공변성을 지정한다.

즉, 클래스 전역에 공변성을 지정할 수 있다.

 

class Box<out T>(val data: T)

 

이러한 선언 지점 변성은 타입 파라미터마다 변성을 계속 지정해야 하는 사용 지점 변성의 단점을 개선한다.

 

출처

https://velog.io/@dhwlddjgmanf/%EC%84%A0%EC%96%B8-%EC%A7%80%EC%A0%90-%EB%B3%80%EC%84%B1%EA%B3%BC-%EC%82%AC%EC%9A%A9-%EC%A7%80%EC%A0%90-%EB%B3%80%EC%84%B1

이펙티브자바

https://asuraiv.tistory.com/16

https://sungjk.github.io/2021/02/20/variance.html

https://dzone.com/articles/variance-in-java

 

반응형

댓글