•
위임 패턴은 상속에 대한 좋은 대안으로 추가적인 보일러 플레이트 코드 없이 사용할 수 있다.
위임이란?
•
한 클래스가 특정 기능을 구현할 때 직접 구현하지 않고 다른 객체에 그 기능을 위임하는 패턴이다.
•
이 패턴은 상속과 달리 더 유연한 코드 구성을 가능하게 한다.
interface Base {
fun print()
}
class BaseImpl(val x: Int) : Base {
override fun print() { print(x) }
}
class Derived(b: Base) : Base by b
fun main() {
val base = BaseImpl(10)
Derived(base).print()
}
Kotlin
복사
•
Base by b는 위임의 핵심 부분으로 b 객체가 Base의 모든 공개 멤버를 대신 처리한다는 의미이다.
위임 동작 원리
•
by 구문은 Derived 클래스가 Base 인터페이스의 모든 메서드를 구현할 필요 없이 b 객체가 이를 대신 처리하게 만든다.
•
Kotlin 컴파일러가 Base 인터페이스의 메서드 구현을 자동으로 생성하고 해당 메서드 호출을 b 객체에 전달하는 역할을 한다.
위임의 장점
•
코드 중복 방지
◦
Derived 클래스가 Base 인터페이스의 메서드를 직접 구현하지 않고도 사용할 수 있기 때문에 중복 코드가 줄어든다.
•
유연성
◦
위임 객체를 바꾸기만 하면 클래스의 동작을 쉽게 변경할 수 있다.
◦
상속과 달리 다중 위임도 가능하므로 다양한 객체로부터 기능을 위임받을 수 있다.
위임된 인터페이스 멤버의 오버라이드
•
위임을 통해 구현한 인터페이스의 특정 멤버를 오버라이드하면 위임된 객체의 멤버 대신 오버라이드된 멤버가 호출된다.
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() {
val base = BaseImpl(10)
Derived(base).printMessage() // 출력: abc
Derived(base).printMessageLine() // 출력: 10
}
Kotlin
복사
•
Derived 클래스에서 printMessage() 메서드를 오버라이드하여 위임된 객체의 메서드보다 우선적으로 호출된다.
위임된 객체의 멤버가 오버라이드된 멤버를 호출하지 않음
•
위임된 객체의 구현에서는 해당 객체의 자체 구현만 호출되며 오버라이드된 멤버는 호출되지 않는다.
interface Base {
val message: String
fun print()
}
class BaseImpl(x: Int) : Base {
override val message = "BaseImpl: x = $x"
override fun print() { println(message) }
}
class Derived(b: Base) : Base by b {
// 위임된 객체에서 이 오버라이드된 message는 접근되지 않음
override val message = "Message of Derived"
}
fun main() {
val b = BaseImpl(10)
val derived = Derived(b)
derived.print() // 출력: BaseImpl: x = 10
println(derived.message) // 출력: Message of Derived
}
Kotlin
복사
•
BaseImpl 클래스는 Derived의 message가 아닌 자신의 message만 참조한다.