일반적인 알고리즘을 구현할 때 제네릭을 사용하라
타입 아규먼트를 사용해 함수에 타입을 전달할 수 있다.
다음은 stdlib의 filter 함수의 예시다.
inline fun <T> Iterable<T>.filter(
predicate: (T) -> Boolean
): List<T> {
val destination = ArrayList<T>()
for (element in this) {
if (predicate(element)) {
destination.add(element)
}
}
return destination
}
타입 파라미터가 컴파일러에게 타입 정보를 전달해, 컴파일 시점에 타입을 알 수 있다.
타입 파라미터의 중요한 기능 중 하나는 구체적인 타입의 서브타입만 사용하게 타입을 제한하는 것이다.
fun <T: Comparable<T>> Iterable<T>.sorted(): List<T> {
/* ... */
}
fun <T, C : MutableCollection<in T>>
Iterable<T>.toCollection(destination: C): C {
/* ... */
}
class ListAdapter<T: ItemAdapter> (/* ... */) { /*...*/ }
: 뒤에 슈퍼타입을 설정해 제한을 걸고 있다. Comparable<T>
로 제한한다면 해당 타입을 비교한다는 것을 알 수 있다.
많이 사용하는 제한으로는 Any가 있으며, nullable이 아닌 타입을 나타낸다.
inline fun <T, R: Any> Iterable<T>.mapNotNull(
transform: (T) -> R?
): List<R> {
return mapNotNullTo(ArrayList<R>(), transform)
}
둘 이상의 제한을 걸 때는 다음과 같이 where
을 사용해 작성할 수 있다.
fun <T> pet(animal: T) where T: Animal, T: GoodTempered {
}