Software Development Engineer @ Amazon
reniowood at gmail.com resume
원본 문서: Delegation - Kotlin Progamming Language
코드의 실행 결과는 원본 문서에는 없으나 직접 실행 후 첨부하였다. 실제로 실행해보려면 원본 문서를 참조하기를 바랍니다.
위임 패턴은 상속 구현의 좋은 대안으로 검증되었다. 코틀린은 위임을 반복적인 코드를 전혀 작성하지 않고도 쓸 수 있도록 제공한다. Derived
클래스는 자신의 모든 공개 멤버를 특정 객체에 위임함으로써 Base
인터페이스를 구현할 수 있다.
interface Base {
fun print()
}
class BaseImpl(val x: Int) : Base {
override fun print() { print(x) }
}
class Derived(b: Base) : Base by b
fun main(args: Array<String>) {
val b = BaseImpl(10)
Derived(b).print()
}
// 결과
10
Derived
클래스의 슈퍼타입 목록에 있는 by 구문은 b
가 Derived
객체 내부에 저장되고 컴파일러가 b
로 전달되는 Base
의 모든 메소드를 생성한다.
컴파일러는 위임한 객체의 메소드 대신 override
구현을 사용할 것이다. override fun print() { print("abc") }
를 Derived
에 추가하면 프로그램은 print
를 호출했을 때 “10”대신 “abc”를 출력한다.
interface Base {
fun printMessage()
fun printMessageLine()
}
class BaseImpl(val x: Int) : Base {
override fun printMessage() { print(x) }
override fun printMessageLine() { println(x) }
}
class Derived(b: Base) : Base by b {
override fun printMessage() { print("abc") }
}
fun main(args: Array<String>) {
val b = BaseImpl(10)
Derived(b).printMessage()
Derived(b).printMessageLine()
}
// 결과
abc10
그러나 멤버 변수를 오버라이드했을 때에는, 직접 접근하면 접근 가능하지만 메소드가 간접적으로 접근하면 원래 구현이 가지고 있는 멤버 변수의 값을 사용한다.
interface Base {
val message: String
fun print()
}
class BaseImpl(val x: Int) : Base {
override val message = "BaseImpl: x = $x"
override fun print() { println(message) }
}
class Derived(b: Base) : Base by b {
// This property is not accessed from b's implementation of `print`
override val message = "Message of Derived"
}
fun main(args: Array<String>) {
val b = BaseImpl(10)
val derived = Derived(b)
derived.print()
println(derived.message)
}
// 결과
BaseImpl: x = 10
Message of Derived