728x90
Kotlin에서 List, Map, Set같은 Collections 클래스를 사용할 때, List<String> 이런식으로 제네릭 타입을 지정할 수 있다.
제네릭을 사용하면 타입 안정성을 얻을 수 있다.
하지만 제네릭으로 지정한 타입 이외에도 좀 더 유연하게 사용하고 싶을 수 있다.
그래서 코틀린에서는 공변성과 반공변성을 허용한다.
package generic
abstract class Animal(val name: String)
abstract class Fish(name: String) : Animal(name)
// 금붕어
class GoldFish(name: String) : Fish(name)
// 잉어
class Carp(name: String) : Fish(name)
|
package generic
fun main(){
val goldFishCage = Cage<GoldFish>()
goldFishCage.put(GoldFish("금붕어")) // Type Casting없이 바로 금붕어를 가져올 수 있다.
val cage = Cage<Fish>()
cage.moveFrom(goldFishCage)
val fish: Fish = cage.getFirst()
// Cage<Fish>에서 데이터를 가져오면 GoldFish인지 Carp인지 모른다.
}
/***
* 제네릭 클래스 : 타입 파라미터를 사용한 클래스
* 코틀린에서는 Raw 타입 사용이 불가능하다.
* Raw Type : 제네릭 클래스에서 타입 매개변수를 사용하지 않고 인스턴스화 하는 것
* in-variant(무공변) : 타입 파라미터끼리는 상속관계이더라도, 제네릭 클래스 간에는 상속관계가 없다는 의미
* co-variant(공변) : 타입 파라미터간의 상속관계가 제네릭 클래스에도 동일하게 유지된다는 의미
* 코틀린에서는 타입 파리미터 앞에 out 변성 어노테이션을 사용한다.
* contra_variant(반공변) : 타입 파라미터간의 상속관계가 제네릭 클래스에서는 반대로 유지된다는 의미
* 코틀린에서는 타입 파리미터 앞에 in 변성 어노테이션을 사용한다.
*/
class Cage<T : Animal> {
private val animals: MutableList<T> = mutableListOf()
fun getFirst() : T {
return animals.first();
}
fun getAll() : List<T> {
return this.animals
}
fun put(animal: T) {
this.animals.add(animal)
}
fun moveFrom(otherCage: Cage<out T>) {
// out을 붙이면 moveFrom 함수를 호출할 때 Cage는 공변하게 된다.
// out을 붙이면, otherCage로부터 데이터를 꺼낼 수만 있다.
this.animals.addAll(otherCage.animals)
}
fun moveTo(otherCage: Cage<in T>){
// in을 붙인 otherCage는 데이터를 받을 수만 있다.
otherCage.animals.addAll(this.animals)
}
}
|
728x90
'안드로이드 > Kotlin 문법' 카테고리의 다른 글
코틀린 클래스 위임(Class Delegation) (1) | 2024.02.06 |
---|---|
[코틀린] ArrayList, mutableListOf (0) | 2021.06.14 |
[코틀린] Inner Class (0) | 2020.08.21 |
[코틀린] Nested Class (중첩 클래스) (0) | 2020.08.21 |
코틀린 클래스 (0) | 2020.05.06 |