Page 30 -
P. 30
자바에서는 캐스트를 활용하거나 리플렉션(reflection)을 통해 타입 소거를 우회해야 한다. 두 방식
모두 단점이 있다. 캐스트는 문제를 (컴파일이 되도록) 덮어버려서 나중에 오류가 발생한다. 반대
로 리플렉션 API를 사용하면 성능에 영향을 미칠 수 있다. 코틀린은 이 두 가지 약점을 모두 극복
할 수 있는 세 번째 해법을 제공한다.
구체화는 타입 파라미터 정보를 런타임까지 유지한다는 뜻이다. 어떻게 컴파일러가 타입 소거를
우회할 수 있을까? 해답은 인라인한 함수에 대해서만 구체화한 타입 파라미터를 쓸 수 있다는 데
있다. 함수 본문을 호출 위치로 인라인시키기 때문에 컴파일러가 인라인된 함수에 제공되는 타입
인자의 실제 타입을 항상 알 수 있다.
파라미터를 구체화하려면 reified 키워드로 해당 타입 파라미터를 지정해야 한다. 이 기능을 활
용해 isInstanceOf() 함수를 고쳐보자. 인라인 함수는 재귀 함수일 수 없으므로 먼저 구현을 약간
수정해야 한다.
fun <T>TreeNode<T>.cancellableWalkDepthFirst(
onEach: (T) -> Boolean
): Boolean {
// 자바 LinkedList는 Deque를 구현하고 있어서 스택으로도 사용 가능함
// 자바 Stack 사용은 권장하지 않음
val nodes = java.util.LinkedList<TreeNode<T>>()
nodes.push(this)
while (nodes.isNotEmpty()) {
val node = nodes.pop()
if (!onEach(node.data)) return false
node.children.forEach { nodes.push(it) }
}
return true
}
inline fun <reified T> TreeNode<*>.isInstanceOf() =
cancellableWalkDepthFirst{ it is T }
이 코드는 별도의 cancellableWalkDepthFirst()라는 인라인되지 않는 함수로 트리 순회 로직을
추출해 사용한다. 예를 들어 이 함수를 다음과 같이 호출할 수 있다.
370
Kotlin_05.indd 370 2022-02-15 오후 4:08:04