我正在尝试扩展javax.swing.Timer,但它只有一个构造函数,即
Timer(int delay, ActionListener listener)
Run Code Online (Sandbox Code Playgroud)
我不希望Scala中的子类ActionListener在其构造函数中使用Java .我在一个非常古老的线程中读到"没有办法直接调用超类构造函数;你必须通过你自己的类的主要构造函数",所以它看起来像我ActionListener在主构造函数中被困住了.所以我添加了一个辅助构造函数:
case class TimerEvent (source: AnyRef) extends swing.event.Event
class ScalaTimer2 (delay: Int, listener: java.awt.event.ActionListener)
extends javax.swing.Timer(delay, listener) with swing.Publisher {
outer =>
def this(delay: Int) = {
this(delay, new java.awt.event.ActionListener {
def actionPerformed(e: java.awt.event.ActionEvent) {
publish(TimerEvent(outer)) // <-- publish not recogonized
}
})
// publish(TimerEvent(outer)) // <-- publish recognized here
}
}
Run Code Online (Sandbox Code Playgroud)
但是我得到了编译错误error: not found: value publish......为什么?以及如何解决?
这里实际上有两个问题:既publish与outer之前的构造已完成将不可用.Scala似乎有一个规则,即this在主构造函数完成之前,实例不能在辅助构造函数中引用.例如,以下将无法编译:
class Foo (x: Unit) { def this() { this(println(this)) } }
Run Code Online (Sandbox Code Playgroud)
而不是辅助构造函数,如何在伴随对象上定义工厂方法?
object ScalaTimer2 {
def apply(delay: Int): ScalaTimer2 = {
lazy val ret: ScalaTimer2 = new ScalaTimer2(delay, new java.awt.event.ActionListener {
def actionPerformed(e: java.awt.event.ActionEvent) {
ret.publish(TimerEvent(ret))
}
})
ret
}
}
Run Code Online (Sandbox Code Playgroud)
注意,前向引用ret需要使用a lazy val而不是just val.据推测actionPerformed,在构造函数返回之前不会调用,否则ret由于无限递归而无效.