지난 시간까지 여러 종류의 클래스와 인터페이스에 대해 학습하였습니다
오늘의 학습 주제는 코틀린의 제네릭(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)이라 합니다
이것으로 오늘의 학습을 마치겠습니다
그럼 이만-_-
'Android' 카테고리의 다른 글
[Android] 코틀린(Kotlin)과 자바(Java)의 상호운용 (0) | 2020.06.07 |
---|---|
[Android] 코틀린(Kotlin)의 실체화(Reification)와 확장(Extension) (0) | 2020.06.07 |
[Android] 코틀린(Kotlin) sealed 클래스, 추상클래스, 인터페이스 (0) | 2020.05.08 |
[Android] 코틀린(Kotlin) 다른 타입의 클래스(Class) (0) | 2020.05.04 |
[Android] 코틀린(Kotlin) 클래스(Class)의 상속(Inheritance)와 타입(Type) (0) | 2020.05.04 |