클래스 위임

클래스 위임 처리

interface Base { fun say() }

class BaseImpl(private val x: Int) : Base {
    override fun say() { println("베이스 클래스 구현 : $x") }
}

class Derived(private val b: BaseImpl) : Base {
    override fun say() { b.say() }
}

class Derived2 : Base by BaseImpl(10)

fun main() {
    val b = BaseImpl(10)
    Derived(b).say() // 베이스 클래스 구현 : 10
    Derived2().say() // 베이스 클래스 구현 : 10
}

생성자의 매개변수 속성으로 위임 처리

interface SoundBehavior { fun makeSound() }

class ScreamBehavior : SoundBehavior {
    override fun makeSound() = println("Screaming!!!")
}

class RockAndRollBehavior : SoundBehavior {
    override fun makeSound() = println("Rock'n'roll!!!")
}

class Person(soundBehavior: SoundBehavior) : SoundBehavior by soundBehavior

fun main() {
    Person(ScreamBehavior()).makeSound() // Screaming!!!
    Person(RockAndRollBehavior()).makeSound() // Rock'n'roll!!!
}

클래스 위임 활용

  1. 내장된 집합 인터페이스를 위임 처리
class CounterSet<T>(
    private val innerSet: MutableSet<T> = mutableSetOf()
) : MutableSet<T> by innerSet {
    var elementAdded: Int = 0
        private set

    override fun add(element: T): Boolean {
        elementAdded++
        return innerSet.add(element)
    }

    override fun addAll(elements: Collection<T>): Boolean {
        elementAdded += elements.size
        return innerSet.addAll(elements)
    }

    fun display(): MutableSet<T> = innerSet
}

fun main() {
    val counterList = CounterSet<String>()
    counterList.addAll(listOf("A", "B", "C", "D", "E"))
    println(counterList.elementAdded) // 5
    println(counterList.display()) // [A, B, C, D, E]
}

<aside> 💡 by 키워드는 CounterSet에 MutableSet의 모든 멤버 함수를 자동으로 복사하는 것처럼 동작함. 실제로 복사되진 않고, 호출 시 위임 객체(innerSet)의 해당 함수가 호출됨.

</aside>

  1. 데이터 저장과 기능 관리를 분리한 클래스 위임
// 잔액 관리 클래스
class Balance(val accountNo: Int, var balance: Int)

// 입, 출금 처리
interface Accountable {
    fun deposit(acc: Balance, amount: Int)
    fun withdraw(acc: Balance, amount: Int)
}

// 입, 출급 구현 클래스
class DWManager : Accountable {
    override fun deposit(acc: Balance, amount: Int) { acc.balance = acc.balance + amount }
    override fun withdraw(acc: Balance, amount: Int) { acc.balance = acc.balance - amount }
}

// 계좌 관리 클래스
class Agreement(
    val accountNo: Int,
    val dwManager: Accountable
) : Accountable by dwManager

fun main() {
    val dwManager = DWManager()
    val b = Balance(1, 0)
    val a = Agreement(1, dwManager)

    a.dwManager.deposit(b, 1000)
    println("계좌번호 : ${a.accountNo}")
    println("계좌번호 : ${b.accountNo} 잔액 : ${b.balance}")
    a.dwManager.withdraw(b, 500)
    println("계좌번호 : ${b.accountNo} 잔액 : ${b.balance}")
}

실행결과
계좌번호 : 1
계좌번호 : 1 잔액 : 1000
계좌번호 : 1 잔액 : 500

속성 위임