如何将实现委托给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()) { } } 
  • Kotlin中的Hadoop上下文types参数
  • kotlin:通用于不同的types
  • 在Kotlin中交换函数
  • 如何将types清除列表转换为Kotlin中的数组?
  • Android w / Kotlin纯java-Junit的NoClassDefFoundError解决方法不起作用
  • 使用包含generics的值创建映射
  • Kotlin数组的toList和asList有何不同?
  • 我如何使用Kotlin运行单个Android测试?
  • 从两个列表中获取不寻常的元素 - KOTLIN
  • 嘲笑Kotlin和Mockito的通用接口
  • Kotlin和详细的数组实例化
  • Kotlin language will be the best programming language for Android.