Как вложить несколько делегатов свойств в Котлин
Я столкнулся со случаем, когда я хочу "связать" несколько делегатов (соединяя выходные данные одного с другим).
Кажется, это возможно:
private val errorLogList by listSO(listOf<StateObject<Luxeption>>(), SODest.NONE, publicSOAccessRights())
val errorLog: StateObject<List<StateObject<Luxeption>>> by addToSet(errorLogList)
Однако это выглядит не очень хорошо:). Я бы хотел сделать это одной строкой вот так:
val errorLog: StateObject<List<StateObject<Luxeption>>> by addToSet(
listSO(listOf<StateObject<Luxeption>>(), SODest.NONE, publicSOAccessRights())
)
Мой вопрос: возможно ли такое создание свойств через делегатов в Котлине?
Вот обе реализации моих делегатов:
добавить к множеству:
open class ChildSOReturner {
val set: Set<StateObject<*>> = setOf()
inline fun <reified T> addToSet(so: T) = object: ReadOnlyProperty<Any?, T> {
override operator fun getValue(thisRef: Any?, property: KProperty<*>): T {
if (thisRef is T) {
set.plus(so)
return so
} else throw IllegalArgumentException()
}
}
}
listSo:
fun <O> listSO(
initialState: List<StateObject<O>>,
soDest: SODest,
soAccessRights: SOAccessRights
) = object : ReadOnlyProperty<Any?, StateObject<List<StateObject<O>>>> {
override operator fun getValue(thisRef: Any?, property: KProperty<*>): StateObject<List<StateObject<O>>> {
val meta = SOMeta(SOId(property.name), soDest, soAccessRights)
return StateObjectList(initialState, meta)
}
}
1 ответ
Это оказалось довольно сложно, но возможно (если я чего-то не упускаю, и это не проверено, но идея должна работать):
fun <T, U, V> composeProperties(prop: ReadOnlyProperty<T, U>, f: (U) -> ReadOnlyProperty<T, V>) : ReadOnlyProperty<T, V> {
var props = mutableMapOf<Pair<T, KProperty<*>>, ReadOnlyProperty<T, V>>()
return object : ReadOnlyProperty<T, V> {
override operator fun getValue(thisRef: T, property: KProperty<*>): V {
val prop1 = props.getOrPut(Pair(thisRef, property)) {
f(prop.getValue(thisRef, property))
}
return prop1.getValue(thisRef, property)
}
}
}
А затем использовать
val errorLog: ... by composeProperties(listSO(...)) { addToSet(it) }