如何将实现委托给Kotlin中的一个属性?

Kotlin使我能够通过委托一个主构造器参数来实现一个接口,如下所示:

class Foo(xs : ArrayList) : List by xs { } 

但是,这展示了支持实施者给用户。 委托给匿名人员似乎也没关系:

 class Foo() : List by ArrayList() { } 

这隐藏了实现细节,但我们无法访问接口提供的function,在这种情况下,这是可变的。

因此,我想将实现委托给一个不在主要构造函数中的属性。 我想要的是类似于

 class Foo() : List by xs { val xs : List = ArrayList() } 

不编译。

是否有可能在类体中明确定义一个属性,并且仍然能够将实现委托给它?

2 Solutions collect form web for “如何将实现委托给Kotlin中的一个属性?”

目前这是不可能的。 在by clause中的expression式只在构造类之前计算一次,所以不能引用该类的符号。

在问题追踪器中有一个请求来允许这个,尽管在Kotlin 1.0中几乎肯定不会支持它。

一个有趣的解决方法, 有时候工作是使你想成为一个委托的属性,而不是默认值的构造函数参数。 这样就可以在子句和类体中访问:

 class Foo(val xs: List = ArrayList()) : List by xs { fun bar() { println(xs) } } 

请记住, xs in xs在这里仍然只计算一次,所以即使xs是一个var属性,也只会使用构造函数中提供的默认值。 这不是一个通用的解决方案,但有时它可以提供帮助。

扩展Alexander Udalov的答案,我想出了一个使用私有基类的解决方案

 private open class FooBase(protected val xs : MutableList) : List by xs { } class Foo() : FooBase(ArrayList()) { fun bar() { xs.add(5) } } 

现在,我可以访问支持接口实现的属性,但不限于该接口提供的操作,同时仍然隐藏用户的实际实现。

注意:尽管它有效,但是从EXPOSED_SUPER_CLASS检查中得到以下IntelliJ IDEA 15 CE的警告: 不推荐使用:子类有效可见性“public”应该与其超类有效可见性“private”相同或更小 。 我不太确定这里弃用的部分是什么意思 – 这个警告是否会在将来被删除,或者在某些时候不会被编译。 无论如何,我们实际上并不需要使用private open类, abstract或者简单地open就可以,因为即使用户被允许创建FooBase的实例,也没有太多的事情可以做到。

更新:

实际上有一个简单而紧凑的解决方案,不会使用任何可疑的行为:

 class Foo private constructor(private val xs: ArrayList) : List by xs { constructor() : this(ArrayList()) { } } 
  • 在KotlinJS中使用标准HTML元素可以安全地输入
  • 如何更改alertdialog上的正面按钮的颜色?
  • Kotlin higherorder函数(可调用引用)编译器崩溃
  • 在Kotlin中创建一个TCP侦听器
  • 没有使用对象的Kotlin lambda
  • Kotlin构建时不会发生Android API版本检查
  • Kotlin的crossinline和noinline有什么不同?
  • 为什么Kotlin印刷声明不要求作出范围澄清?
  • 在比较中无视Triple的组件
  • 目录路径列表中的节点层次结构
  • 使用Kotlin中的方法为variables赋值一个新的值?
  • Kotlin language will be the best programming language for Android.