다음과 같은 제네릭 클래스가 있다.
class Cup<T>
위 코드에서 타입 파라미터 T 는 variance 한정자(out 또는 in )가 없다. 이럴 때는 기본적으로 invariant(불공변성)이다. invariant라는 건 제네릭 타입으로 만들어지는 타입들이 서로 관련성이 없다는 뜻. 말하자면 Cup<String> 과 Cup<Hoon> , Cup<Sal> 은 전혀 관계없다.
불공변성 관계
fun main() {
val anys: Cup<Any> = Cup<Int> //Error: Type mistach
val nothings: Cup<Nothing> = cup<Int>() // Error
}
만약 어떤 관련성을 원한다면 out 또는 in 이라는 variance 한정자를 붙인다. out 은 타입 파라미터를 covariant(공변성)로 만든다. 이는 A가 B의 서브타입일 때 Cup<A> 가 Cup<B> 의 서브타입이라는 의미다.
공변성 관계
class Cup<out T>
open class Dog
class Puppy: Dog()
fun main() {
val b: Cup<Dog> = Cup<Puppy> // OK
val a: Cup<Puppy> = Cup<Dog> // Dog은 Puppy의 서브타입이 아니므로 Error
val anys: Cup<Any> = Cup<Int>() //out T로 선언해서 이번엔 OK
val nothings: Cup<Nothings> = Cup<Int>() // Error
}
in 한정자는 반대 의미다. 타입 파라미터를 contravariant(반변성)으로 반든다. 이것은 A가 B의 서브타입일 때, Cup<A> 가 Cup<B> 의 슈퍼타입이라는 것을 의미한다.
class Cup<in T>
open class Dog
class Puppy(): Dog()
fun main() {
val b: Cup<Dog> = Cup<Puppy>() // type mismatch
val a: Cup<Puppy> = Cup<Dog>() // OK
val anys: Cup<Any> = Cup<Int>() // type mismatch
val nothins: Cup<Nothing> = Cup<Int>() // OK
}
varience 한정자를 그림으로 나타내면 다음과 같다
참고: 이펙티브 코틀린 아이템 24
'Kotlin' 카테고리의 다른 글
Koltin Properties (0) | 2021.08.01 |
---|---|
[Kotlin] 코틀린이 null을 다루는 방식 ? 연산자와 ?: 엘비스 연산자 (0) | 2021.05.15 |