Generic의 공변성(Covariance)과 불공변성(Contravariance)

지프치프·2022년 8월 16일
0

Java/Kotlin

목록 보기
9/12
post-thumbnail

개요

Generic의 특징으로 가변성(Variance)이 존재한다.
Type Parameter가 클래스 계층에 영향을 주는 것을 의미하는데
쉽게 말하면 Type의 범위를 지정해준다고 생각하면 될 거 같다.
아래에서 자세히 살펴보자

가변성(Variance)의 유형

가변성에는 3가지 유형이 있다.
제목에는 2가지만 적었지만
설명에 사용할 예시는
Box<T1> / Box<T2> 가 있다고 가정해보자

  • 공변성(Covariance)
    T2가 T1의 SubClass이면 Box<T2>Box<T1>의 하위 자료형이다.

  • 반공변성(ContraVariance)
    공변성의 반대라고 생각하면 편하다
    T2가 T1의 SubClass라면 Box<T2>Box<T1>의 상위 자료형이다.

  • 무변성(Invariance)
    Box<T1>Box<T2>는 아무 관계가 없다.
    즉 Type Parameter가 서로 부모-자식 관계여도 Generic으로 선언된 이후 에는 관계는 성립되지 않는다.
    Generic을 선언하면 기본적으로 무변성이다.

공변성(Covariance)

공변성은 Generic을 선언할 때 out키워드를 작성해주면 된다.
아래는 예제이다.

val co: CovarianceClass<Number> = CovarianceClass<Int>(2)


class CovarianceClass<out T>(t: T) {
    init {
        println("this is $t") // printed 2
    }
}

변수 co의 Type은 CovarianceClass<Number>이지만
정의는 CovarianceClass<Int>(2)로 하였다.
out 키워드로 상하 관계를 지정해주었기에 허용되는 것을 볼 수 있다.

반공변성(Contravariance)

반공변성은 반대로 in 키워드를 작성해주면 된다.

val con: ContravarianceClass<Int> = ContravarianceClass<Number>(2.3)

class ContravarianceClass<in T>(t: T) {
    init {
        println("this is $t") // printed 2.3
    }
}

변수 con의 Type은 ContravarianceClass<Int>
in 키워드를 통해 반공변성을 허용했기 때문에
Int의 상위 클래스인 Number로 정의되는 것을 볼 수 있다.

하지만 여기서 한가지 재밌는 것은
매개변수로 넘긴 값 2.3은 Double이다.

Int로 정의되었지만 반공변성을 통해 Number를 받고
Double이 Number의 서브클래스 이기에 가능한 것으로 보인다.

개인적으로 공부했던 것을 바탕으로 작성하다보니
잘못된 정보가 있을수도 있습니다.
인지하게 되면 추후 수정하겠습니다.
피드백은 언제나 환영합니다.
읽어주셔서 감사합니다.

profile
지프처럼 거침없는 개발을 하고싶은 개발자

0개의 댓글