我想通过使用接口在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代码不同,它确实可以按照您的期望工作(:
接口正文中的每个字段声明都是隐式
public
,static
和final
。
您可以通过将字段放入伴侣对象中实现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()