【问题标题】:How to nest multiple property delegates in Kotlin如何在 Kotlin 中嵌套多个属性委托
【发布时间】:2020-05-24 01:50:01
【问题描述】:

我遇到过一种情况,我想“链接”多个代表(将一个的输出通过管道传递到另一个)。

这似乎是可能的:

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())
)

我的问题:这种类型的通过委托创建属性在 Kotlin 中是否可行?


这是我的代表的两个实现:

addToSet:

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()
        }
    }
}

列表:

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)
    }

}

【问题讨论】:

标签: kotlin delegates delegation kotlin-delegate


【解决方案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) }

【讨论】:

  • 有没有办法将 composeProperties(..) { addToSet(it) } 组合成像 addComposed(..) 这样的调用?我似乎无法弄清楚。
猜你喜欢
  • 2017-12-22
  • 2015-09-02
  • 1970-01-01
  • 1970-01-01
  • 2017-01-18
  • 2017-07-14
  • 1970-01-01
  • 1970-01-01
  • 2023-04-02
相关资源
最近更新 更多