Page 22 -
P. 22
private set
val children: List<TreeNode<T>> get() = _children
fun addChild(data: T) = TreeNode(data).also {
_children += it
it.parent = this
}
override fun toString() =
_children.joinToString(prefix = "$data {", postfix = "}")
}
fun main() {
val root = TreeNode("Hello").apply {
addChild("World")
addChild("!!!")
}
println(root) // Hello {World {}, !!! {}}
}
클래스의 타입 파라미터를 각괄호 안에 써야 한다. 타입 파라미터는 클래스 이름 바로 뒤에 온다.
타입 파라미터 이름은 아무 이름이나 가능하지만, 관습적으로 T, U, V 등의 (짧은) 대문자를 사용
한다. 클래스 안에서는 타입 파라미터를 변수나 프로퍼티, 함수의 타입이나 다른 제네릭 선언의
타입 인자로 쓸 수 있다.
자바 vs. 코틀린 제네릭 클래스나 인터페이스를 사용해 데이터의 타입을 지정할 때는 반드시 타입
인자를 명시해야 한다. TreeNode처럼 타입 파라미터를 지정하지 않은 로타입(raw type)을 사용할
수 있는 자바와 달리, 코틀린에서는 이를 허용하지 않는다. 코틀린에서는 TreeNode<String>처럼
구체적인 타입을 지정하거나, TreeNode<U>처럼 타입 인자로 받은 타입을 반드시 지정해야 한다.
제네릭 클래스 생성자를 호출할 때는 타입 인자가 불필요한 경우가 자주 있다. 대부분의 경우 컴
파일러가 문맥에서 타입 인자를 추론해준다. 그러므로 앞의 예제 코드에서 TreeNode("Hello")처
럼 생성자를 호출할 수 있다. 다만 상위 클래스 생성자에 대한 위임 호출은 예외다. 예제 코드를
약간 바꿔보자.
open class DataHolder<T>(val data: T)
// 실제 타입을 상위 타입의 타입 인자로 넘김
362
Kotlin_05.indd 362 2022-02-15 오후 4:08:04