Kotlin/포스팅

코틀린 선언 지점 변성

짜집퍼박사(짜박) 2024. 1. 2. 21:43

코틀린에서 선언 지점 변성(Declaration-site variance)은 제네릭 타입의 변성을 타입 선언 시점에서 지정하는 방식을 의미합니다. 이는 클래스나 인터페이스를 선언할 때 타입 파라미터의 변성을 결정하는 것을 말합니다. 코틀린에서는 out과 in 키워드를 사용하여 선언 지점 변성을 지정합니다.

 

out 키워드 (공변성 - Covariance)

out 키워드를 사용하여 타입 파라미터가 해당 타입이나 그 하위 타입으로만 사용되도록 선언할 수 있습니다. 이는 주로 타입을 "생산"하는 경우에 사용됩니다.

interface Producer<out T> {
    fun produce(): T
}

fun useProducer(producer: Producer<out Any>) {
    // 생산된 값을 사용하는 로직
}

val stringProducer: Producer<String> = // ...
useProducer(stringProducer) // Producer<out Any>로 사용 가능

Producer<out T>에서 out 키워드는 T가 공변적이라는 것을 나타냅니다. 따라서 Producer<String>은 Producer<Any>의 하위 타입으로 간주됩니다.

 

in 키워드 (반공변성 - Contravariance)

in 키워드를 사용하여 타입 파라미터가 해당 타입이나 그 상위 타입으로만 사용되도록 선언할 수 있습니다. 이는 주로 타입을 "소비"하는 경우에 사용됩니다.

interface Consumer<in T> {
    fun consume(item: T)
}

fun useConsumer(consumer: Consumer<in String>) {
    // 소비 로직
}

val anyConsumer: Consumer<Any> = // ...
useConsumer(anyConsumer) // Consumer<in String>으로 사용 가능

Consumer<in T>에서 in 키워드는 T가 반공변적이라는 것을 나타냅니다. 따라서 Consumer<Any>은 Consumer<in String>의 하위 타입으로 간주됩니다.

 

inout 키워드 (무변성 - Invariance)

무변성은 타입 파라미터가 불변적이어야 함을 나타냅니다. inout 키워드는 코틀린에서는 지원되지 않습니다. 기본적으로 무변성이 적용되며, 생산자와 소비자 모두에서 사용 가능한 공통 타입으로 취급됩니다.

class Box<T>(val value: T)

fun useBox(box: Box<out Any>) {
    // Box<T>에서 T는 공변적
}

fun main() {
    val stringBox: Box<String> = // ...
    useBox(stringBox) // Box<out Any>로 사용 가능
}

이렇게 선언 지점 변성을 사용하면 제네릭 타입을 보다 유연하게 활용할 수 있습니다. 그러나 사용 시 주의할 점은 변성 규칙을 지켜야 하며, 공변성과 반공변성을 혼합해서 사용할 때는 적절한 상황에서 사용해야 합니다.

 

With ChatGPT