kyucumber
전체 글 보기

이펙티브 코틀린 아이템 22. 일반적인 알고리즘을 구현할 때 제네릭을 사용하라

아규먼트로 함수에 값을 전달할 수 있는 것 처럼, 타입 아규먼트를 사용해 함수에 타입을 전달할 수 있다.

타입 아규먼트를 사용하는 함수를 제네릭 함수라고 부른다.

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의 서브타입인 경우 T 타입을 기본으로 반복 처리가 가능하고, 반복 처리때 사용되는 객체가 Int라는 것을 알 수 있다.

많이 사용하는 제한 중 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

  • 이펙티브 코틀린 - 프로그래밍 인사이트, 마르친 모스칼라 지음, 윤인성 옮김

개인적인 기록을 위해 작성된 글이라 잘못된 내용이 있을 수 있습니다.

오류가 있다면 댓글을 남겨주세요.

Table of contents