(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
- 상세 예제나 설명은Kotlin In Action 7.5.3 위임 프로퍼티 구현 참고
- by 키워드를 사용한 프로퍼티 위임. (≈ getter setter 구현 위임)
- 프로퍼티를 호출하면 위임 대상의 getValue, setValue가 호출되는 것이 원리.
- Delegates.notNull() 위임 예제 (lateinit을 사용할 수 있지만 동작이 약간 다르다)
- 객체 변경 시 UI 통지 등에 쓰는, 옵저버 패턴을 위한
Delegates.observable
등
This post is licensed under CC BY 4.0 by the author.