타입 파라미터
를 받는 타입을 정의할 수 있다.List<String>
Map<K, V>
val authors = listOf(”Dmitry”, “Svetlana”)
val authors = listOf<String>
val authors: List<String> = listOf()
<aside> 💡 자바와 달리 코틀린에선 제네릭 타입의 타입 인자를 프로그래머가 명시하거나 컴파일러가 추론할 수 있어야 한다.
</aside>
리스트를 다루는 함수를 작성한다면 특정 타입 ex) List<String> 뿐만 아니라 모든 리스트를 다룰 수 있는 함수를 원할 것이다. → 제네릭 함수 작성
제네릭 함수를 호출할 땐 반드시 구체적인 타입 인자를 넘겨야한다.
fun <T> List<T>.slice(indices: IntRange): List<T>
val letters = ('a'..'z').toList()
println(letters.slice<Char>(0..2)) // 명시적으로 타입인자 지정
>> [a, b, c]
println(letters.slice(10..13)) // 타입 추론
>> [k, l, m, n]
컴파일러는 반환 타입 List<T>의 T를 자신이 추론한 Char로 치환한다.
val authors = listOf("Dmitry", "Svetlana")
val readers = mutableListOf<String>(...)
fun <T> List<T>.filter(predicate: (T) -> Boolean): List<T>
readers.filter { it !in authors } // it의 타입은 T타입 -> String
val <T> List<T>.penultimate: T
get() = this[size - 2]
println(listOf(1, 2, 3, 4).penultimate)
>> 3
<aside> 💡 확장 프로퍼티만 제네릭하게 만들 수 있다. 일반 프로퍼티는 타입 파라미터를 가질 수 없다. 클래스 프로퍼티에 여러 타입의 값을 저장할 수 는 없으므로 제네릭한 일반 프로퍼티는 말이 되지 않음.
val <T> x: T = TODO() // 에러
</aside>
이름 뒤에 타입 파라미터를 넣은 꺽쇠 기호(<>
)를 넣으면 클래스와 인터페이스도 제네릭하게 만들 수 있다.