初始化接口实例变量



我想通过使用接口在kotlin类中注入(富集(行为和状态。像class Impl : Observable一样,可观察的其中包含状态。

在Scala中使用特质(确实有效(,为此寻找Kotlin解决方案:

object Test extends App {
  val impl = new Impl()
  val observer = new Observer()
  impl.register(observer)
}
trait Observable {
  // How to do this in Kotlin?
  val observers = List()
  def register(observer: Observer) {
    observers.add(observer)
  }
}
class Observer
class Parent
class Impl extends Parent with Observable

尝试在kotlin(不工作(:

fun main(args: Array<String>) {
    val impl = Impl()
    val observer = Observer()
    impl.register(observer)
}
interface Observable {
    // Error: Kotlin: Property initializers are not allowed in interfaces
    val observers = mutableListOf<Observer>()
    fun register(observer: Observer) {
        observers.add(observer)
    }
}
class Observer
open class Parent
class Impl : Parent(), Observable

它在接口实例变量线上导致此错误:Kotlin: Property initializers are not allowed in interfaces。如何在Kotlin接口中初始化实例变量?(请注意,在此设计中,不应更改/更新父类。(

更新:我在Java中有一个示例解决方案,但这不是正确的。Java接口中的"实例变量"自动静态。所以我删除了该示例。

您可以在Kotlin界面中具有占位符,并让实现类提供该状态。因此,界面可以提供针对预期到存在的状态的功能。例如:

class Observer
interface Observable {
    val observers: MutableList<Observer> // not present, but expected
    fun register(observer: Observer) {
        observers.add(observer)
    }
}
open class Parent
class Impl : Parent(), Observable {
    override val observers = mutableListOf<Observer>() // used by the interface
}

这是有充分理由的,存在着微妙的问题,即从类层次结构中有多个项目出现的状态,而Kotlin则阻止了此类模型可能引起的问题。

在Java中您实际上有一个静态字段,而不是实例字段(与Scala代码不同,它确实可以按照您的期望工作(:

接口正文中的每个字段声明都是隐式publicstaticfinal

您可以通过将字段放入伴侣对象中实现Kotlin中的相同行为。

但是您实际要做的就是使用abstract class代替接口。

或委托:

interface Observable {
    fun register(observer: Observer)
}
class ObserverList : Observable {
    val observers = mutableListOf<Observer>()
    override fun register(observer: Observer) {
        observers.add(observer)
    }
}
class Impl : Parent(), Observable by ObserverList()

最新更新