코틀린 스터디/이펙티브 코틀린

아이템22) 일반적인 알고리즘을 구현할 때 제네릭을 사용하라

막이86 2024. 8. 8. 10:35
728x90
  • 타입 아규먼트를 사용하는 함수를 제네릭 함수라고 부름
    • 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
    }
    
  • 타입 파라미터는 컴파일러에게 타입과 관련된 정보를 제공하여 컴파일러가 타입을 조금 더 정확하게 추측할 수 있게 해줌
  • filter 함수에서 컴파일러가 아규먼트가 컬렉션의 요소와 같은 타입이라는 것을 알 수 있으므로 잘못 처리하는 것을 막을 수 있음
  • 제네릭은 기본적으로 List<String> 또는 Set<User>처럼 구체적인 타입으로 컬렉션을 만들 수 있게 클래스와 인터페이스에 도입된 기능
  • 코틀린은 강력한 제네릭 기능을 갖고 있지만 복잡해서 이해하기 어려움
    • 많은 코틀린 개발자가 variance 한정자를 어떤 형태로 사용하는지 잘 모름

제네릭 제한

  • 타입 파라미터의 중요한 기능 중 하나는 구체적인 타입의 서브타입만 사용하게 타입 제한
    • 콜론 뒤에 슈퍼타입을 설정해서 제한
    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>() {
    	...
    }
    
  • 타입에 제한이 걸리므로, 내부에서 해당 타입이 제공하는 메서드를 사용할 수 있음
  • 많이 사용하는 제한으로는 Any가 있음
    • nullable이 아닌 타입을 나타냅
    inline fun <T, R: Any> Iterable<T>.mapNotNull(transform: (T) -> R?): List<R> {
    	return mapNotNullTo(ArrayList<R>(), transform)
    }
    
  • 드물지만 둘 이상의 제한을 걸 수 있음
fun <T: Animal> pet(animal: T) where T: GoodTempered {
	...
}

fun <T> pet(animal: T) where T: Animal, T: GoodTempered {
	...
}

정리

  • 코틀린 자료형 시스템에서 타입 파라미터는 중요한 부분
  • 일반적으로 이를 사용해서 type-safe 제네릭 알고리즘과 제네릭 객체를 구현
  • 타입 파라미터는 구체 자료형의 서브타입을 제한할 수 있음
    • 특정 자료형이 제공하는 메서드를 안전하게 사용 가능
728x90