【问题标题】:Kotlin delegation to expression instead of fixed referenceKotlin 委托表达而不是固定引用
【发布时间】:2016-05-10 02:41:25
【问题描述】:

假设我有一个定义为接口的非常复杂的规范:

interface Spec {
    fun sayHello()
}

还有一个标准的实现:

class Impl(private val msg: String) : Spec {
    override fun sayHello() {
        println(msg)
    }
}

现在假设我想创建一个实现该规范并委托给实现的类,但确切的委托对象在对象的整个生命周期内是可变的。这是一个例子:

class Derived(var target: Spec) : Spec by target

上例的问题是构造函数调用时构造函数参数target被设置为委托对象。然后类直接访问委托,而不是执行属性访问。 (这已通过查看 Kotlin 生成的字节码得到证实。)

因此,即使在构造类之后修改了属性target,委托也不会改变。

任何人都可以提供一种在 Kotlin 中执行此委托的方法,而无需编写每个方法吗?

理想的解决方案还允许委托给像 lambda 或其他表达式这样通用的东西,只要在对象的整个生命周期中需要委托,就可以评估并用作委托。

【问题讨论】:

    标签: java delegates kotlin


    【解决方案1】:

    目前没有办法做到这一点。见Kotlin issue KT-5870

    当前 Kotlin 在类初始化器中评估委托的表达式

    【讨论】:

      【解决方案2】:

      您可以添加一个间接级别:

      class Holder(var impl: Spec) : Spec {
          override fun sayHello() = impl.sayHello()    
      }
      
      class Derived(target: Spec, 
                    private val holder: Holder = Holder(target)) : Spec by holder {
      
          fun changeTarget(newTarget: Spec) {
              holder.impl = newTarget
          }
      }
      

      不幸的是,holder 必须是构造函数参数才能与委托构造一起使用(对于 Kotlin v1.0),因此它会使主构造函数复杂化。

      【讨论】:

      • 在这种情况下,您必须手动委托作者试图避免的所有方法。
      • @Michael 是的,这是真的,但是我只需为 Holder 执行一次手动委托,之后我就可以使用它而无需额外的样板文件
      • 您不需要任何额外的课程。只需将所有内容都委托给Derived
      • 是的,但我必须手动委派Derived2Derived3 等。Handle 将这一切集中在一个地方
      • @voddan 仅当他获得多个 Derived 时。从作者所说,不清楚他是否得到了 Derived2/3/4
      猜你喜欢
      • 2019-01-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-10-18
      • 1970-01-01
      • 1970-01-01
      • 2017-11-28
      • 1970-01-01
      相关资源
      最近更新 更多