Android

[Android] 코틀린(Kotlin) 제네릭(Generic)

구루싸 2020. 5. 17. 21:03
반응형
SMALL

지난 시간까지 여러 종류의 클래스와 인터페이스에 대해 학습하였습니다

오늘의 학습 주제는 코틀린의 제네릭(generic)에 대해 알아보겠습니다

제네릭은 클래스와 인터페이스의 매개변수

또는 함수의 매개변수와 반환 타입을 미리 확정하지 않고

정의한 후에 사용되는 시점에서 특정 타입을

지정할 수 있도록 해주는 기법을 말합니다

/* type constraint */
class LootBox<T: Loot>(vararg item: T) {
    var open = false
    private var loot: Array<out T> = item

    operator fun get(index: Int): T? = loot[index].takeIf { open }
    
    fun fetch(item: Int): T? {
        return loot[item].takeIf { open }
    }

    fun <R> fetch(item: Int, lookModFunction: (T) -> R): R? {
        return lookModFunction(loot[item]).takeIf { open }
    } 
}

open class Loot(val value: Int)

class Fedora(val name: String, value: Int): Loot(value)

class Coin(value: Int): Loot(value)

fun main(args: Array<String>) {
    val lootBoxOne: LootBox<Fedora> = LootBox(Fedora("Ordinary fedora", 15), 
                                              Fedora("Dazzling purple fedora", 25))
    val lootBoxTwo: LootBox<Coin> = LootBox(Coin(15))

    lootBoxOne.open = true
    lootBoxOne.fetch(1)?.run {
        println("Took $name out of the LootBox.")
    }
    
    val coin = lootBoxOne.fetch(0) {
        Coin(it.value * 3)
    }
    coin?.let { println(it.value) }
    
    val fedora = lootBoxOne[1]
    fedora?.let { println(it.name) }
}

위의 코드에서 T가 제네릭 타입 변수이며

<> 안에 지정되고 T는 item 매개변수의 타입입니다

제네릭 타입 매개변수 이름은 어떤 문자나 단어도 가능한데

아래의 표의 표준화된 명칭을 따르는 것이 좋습니다

문자 설명
E 컬렉션에 저장되는 요소(Entity)를 나타낸다
K 키(Key)를 나타낸다
N 숫자(Number) 타입을 나타낸다
T 모든 타입(Type)을 나타낸다
V 값(Value)을 나타낸다
R 함수의 반환(Return)값을 나타낸다

위의 코드에서 제네릭 함수 fetch를 볼 수 있습니다

T? 타입의 아이템을 반환하는 fetch와

R? 타입을 반환하는 fetch가 있습니다

lootModFunction은 fetch 함수의 매개변수 이름이면서

이 매개변수에 전달되는 함수의 매개변수 타입과

반환 타입을 정의하기 위해 사용된 함수 이름이며

(T) -> R 로 표현된 부분은 함수 타입(function type)입니다

클래스 LootBox은 타입 제약(type constraint)인

<T: Loot>로 인해 Loot 클래스와 서브 클래스만

LootBox 클래스의 매개변수 타입으로 사용될 수 있으며

vararg 키워드를 통해 매개변수가 배열로 처리되게하여

여러 개의 아이템을 인자로 받을 수 있고

연산자[]을 오버로딩하는 get 함수를 정의하였네요

마지막으로 loot 선언부에 키워드 out을 보겠습니다

제네릭 클래스의 인스턴스는 원시 타입과 제네릭 타입이

결합된 것이 자신의 타입이 되고

<>로 나타낸 제네릭 타입 간의 슈퍼-서브 관계가 있어도

컴파일러가 인식하지 못하게 되는데

이를 in과 out을 이용하면 컴파일러가 고려해줍니다

예를 들면 코틀린의 읽기 전용 컬렉션 중에 List<out E>입니다

제네릭 타입 매개변수에 out 키워드를 지정한 것을 공변형(covariance)

in 키워드를 지정한 것을 반공변형(contravariance)이라 합니다

이것으로 오늘의 학습을 마치겠습니다

그럼 이만-_-

반응형
LIST