Search

Delegation

위임 패턴은 상속에 대한 좋은 대안으로 추가적인 보일러 플레이트 코드 없이 사용할 수 있다.

위임이란?

한 클래스가 특정 기능을 구현할 때 직접 구현하지 않고 다른 객체에 그 기능을 위임하는 패턴이다.
이 패턴은 상속과 달리 더 유연한 코드 구성을 가능하게 한다.
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만 참조한다.