코틀린 고급편 강의를 수강한 후, 정리한 글입니다
클래스를 공변하게 만드는 방법
제너릭 클래스 자체를 공변하게 만들 수 있는 방법은 없을까? 코틀린에서는 클래스에서의 공변이 가능하다.
생산만 하는 클래스 Cage3. 내보내기만 하고 있는 클래스이다. 이럴 경우에는 클래스 자체를 공변하게 만들 수 있다.
class Cage3<T> {
private val animals: MutableList<T> = mutableListOf()
fun getFirst(): T {
return this.animals.first()
}
fun getAll(): List<T> {
return this.animals
}
}
클래스 자체가 공변하다면 다음과 같을 때, 에러 발생이 나지 않을 것이다.
val fishCage: Cage3<Fish> = Cage3()
val animalCage: Cage3<Animal> = fishCage
다음과 같이 구현하면 된다. class 자체를 공변하게 만들기 위해서는 class 에 있는 type parameter 에 out
을 붙여주면 된다. 소비를 위한 T 를 받는 순간 type 안정성이 깨지기 때문에 생산만 가능하다.
fun main() {
val fishCage = Cage3<Fish>()
val animalCage: Cage3<Animal> = fishCage
}
class Cage3<out T> {
private val animals: MutableList<T> = mutableListOf()
fun getFirst(): T {
return this.animals.first()
}
fun getAll(): List<T> {
return this.animals
}
}
소비만 하는 클래스의 경우에는 반대로 반공변하게 클래스를 만들줄 수 있다.
class Cage4<in T> {
private val animals: MutableList<T> = mutableListOf()
fun put(animal: T) {
this.animals.add(animal)
}
fun putAll(animals: List<T>) {
this.animals.addAll(animals)
}
}
클래스를 선언하는 지점에 변성을 주는 것을 declaration-site variance, 함수에서 사용하는 시점에 변성을 주는 것을 use-site variance 라고 부른다. 클래스 자체에 변성을 주는 방식은 자바에는 존재하지 않는다고 한다…
근데 사실 애초에 데이터를 받기만 한다거나, 주기만 한다거나 하는 클래스는 흔한 케이스는 아니다. 함수 파라미터에 @UnsafeVariance
라는 어노테이션을 붙이면 클래스 자체에 변성을 주더라도 클래스와 다른 성격의 소비/생산을 할 수 있도록 할 수는 있다.
'[ Kotlin ]' 카테고리의 다른 글
lateinit 과 lazy (0) | 2024.08.30 |
---|---|
코틀린의 제네릭 제약과 제너릭 함수 (0) | 2024.08.29 |
코틀린의 배열과 리스트, 제너릭과 무공변, 공변, 반공변 (1) | 2024.08.29 |
코틀린의 제너릭과 타입 파라미터 (0) | 2024.08.29 |
코틀린의 scope function - 20강 (0) | 2024.08.29 |