아규먼트로 함수에 값을 전달할 수 있는 것 처럼, 타입 아규먼트를 사용해 함수에 타입을 전달할 수 있다.
타입 아규먼트를 사용하는 함수를 제네릭 함수라고 부른다.
inline fun <T> Iterable<T>.filter(
predicate: (T) -> Boolean
): List<T> {
// ...
}
타입 파라미터는 컴파일러에 타입과 관련된 정보를 제공해 컴파일러가 타입을 조금이라도 더 정확하게 추측할 수 있게 해준다. filter에서 아규먼트가 컬렉션의 요소와 같은 타입이라는 것을 알 수 있으므로 잘못 처리하는것을 막을 수 있다.
컴파일 과정에서 최종적으로 이러한 타입 정보는 사라지지만, 개발 중에는 타입 정보를 이용해 안전하게 사용할 수 있다.
제네릭 제한
타입 파라미터의 중요한 기능 중 하나는 구체적인 타입의 서브타입만 사용하게 타입을 제한하는 것이다.
아래에서는 콜론 뒤에 슈퍼타입을 설정해 타입에 제한을 건다.
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>(/*..*/) { }
타입에 제한이 걸리므로, 내부에서 해당 타입이 제공하는 메소드를 사용할 수 있다.
예를 들어 T가 Iterable
많이 사용하는 제한 중 Any도 있다. 이는 nullable이 아닌 타입을 나타낸다.
inline fun <T, R : Any> Iterable<T>.mapNotNull(
transform: (T) -> R?
): List<R> {
// ..
}
아래와 같이 둘 이상의 제한을 걸수도 있다. 둘 이상의 제약을 걸때는 where
키워드를 사용한다.
fun <T: Animal> pet(animal: T) where T: GoodTempered {
// ..
}
fun <T> pet(animal: T) where T: Animal, T: GoodTempered {
// ..
}
정리
타입 파라미터를 이용해 type-saf 제네릭 알고리즘과 제네릭 객체를 구현하기 때문에 코틀린에서 타입 파라미터는 굉장히 중요한 부분이다.
타입 파라미터는 구체적인 자료형(concrete type)의 서브타입을 제한할 수 있으며 이렇게 하면 특정 자료형이 제공하는 메소드를 안전하게 사용할 수 있다.
Reference
- 이펙티브 코틀린 - 프로그래밍 인사이트, 마르친 모스칼라 지음, 윤인성 옮김
개인적인 기록을 위해 작성된 글이라 잘못된 내용이 있을 수 있습니다.
오류가 있다면 댓글을 남겨주세요.