Post

(Kotlin) delegate 키워드 - by

클래스 delegation (컴포지션, composition)

  • 상속을 허용하지 않는 클래스에 새로운 동작을 추가해야 할 때(Wrapping) 또는 메소드의 동작을 변경하고 싶을 때 위임을 사용하게 되는데 단점이 준비 코드가 너무 많이 필요하다는 점 이다.
  • 아래와 같이 innerList를 Wrapping하게 되면 위와 같이 굳이 재정의하고 싶지 않은, 단순히 원래 클래스로 전달하고 싶은 코드도 모두 재정의해야 하기 때문에 상당히 난잡해진다.
1
2
3
4
5
6
7
8
9
10
11
12
13
class DelegatingCollection0<T>(
    private val innerList: ArrayList<T> = arrayListOf<T>()
) : Collection<T> {

    override val size: Int get() = innerList.size
    override fun isEmpty() : Boolean = innerList.isEmpty()
    override fun contains(element: @UnsafeVariance T): Boolean =
        innerList.contains(element)
    override fun iterator(): Iterator<T> = innerList.iterator()
    override fun containsAll(elements: Collection<@UnsafeVariance T>): Boolean =
        innerList.containsAll(elements)
}

by 키워드를 사용하면 이를 자동으로 처리해준다!
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
class CountingSet<T>(
    private val innerSet: MutableCollection<T> = HashSet<T>()
) : MutableCollection<T> by innerSet {

    var objectsAdded = 0

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

// 반드시 생성자에서 받을 필요는 없다.
@Component
class LocalOrderBookContainer private constructor(
    private val applicationEventPublisher: ApplicationEventPublisher,
    private val container: ConcurrentHashMap<String, OrderBook>
) : ConcurrentMap<String, OrderBook> by container {
    // 여기서 Map<>으로 설정하면, Map 인터페이스가 된다!

    @Autowired constructor(
        applicationEventPublisher: ApplicationEventPublisher
    ): this(applicationEventPublisher, ConcurrentHashMap<String, OrderBook>())
}
  • delegation 타입을 어떻게 설정하느냐에 따라 외부 인터페이스를 다르게 줄 수 있다.
  • 기능을 변경하고 싶은 메소드만 명시적으로 오버라이드하면 된다.
  • 명시적으로 오버라이드된 메소드가 있을 경우 그 메소드가 호출되고, 오버라이드 하지 않은 메서드는 같은 이름의 innerSet 메서드로 연결된다.
  • https://medium.com/til-kotlin-ko/kotlin의-클래스-위임은-어떻게-동작하는가

delegation 대상이 될 필드는 val 이어야 한다. (var는 불가)

프로퍼티 delegation

This post is licensed under CC BY 4.0 by the author.