为什么抽象覆盖失败

时间:2016-07-29 20:40:31

标签: scala akka mixins

我发现使用抽象类型会影响scala编译器检测覆盖的能力,并将看似正确的代码解释为错误。

trait I {
  type T
  def doThings(t : T) : Unit
}
type IT[X] = I { type T = X}

trait A extends I {
  override type T = AnyRef
  def doThings(t : T) : Unit = println("A")
}

trait Z[X] extends I { this : IT[X] =>
  abstract override def doThings(t : T) : Unit = {
    println("Z")
    super.doThings(t)
  }
}

object Use {
  val az = new A with Z[AnyRef] {}
}

scala编译器触发了这样的错误:

OverloadAbstract.scala:44: error: object creation impossible, since method doThings in trait Z of type (t: this.T)Unit is marked `abstract' and `override', but no concrete implementation could be found in a base class
    val az = new A with Z[AnyRef] {}

在特质混合和实施之间表达这种关系的正确方法是什么?

为了比较代码工作正常:

trait I {
  def doThings() : Unit
}

class A extends I {
  def doThings() : Unit = println("A")
}

trait Z extends I {
  abstract override def doThings() : Unit = {
    println("Z")
    super.doThings()
  }
}

object Use {
  val az = new A with Z {}
}

真正的用例是为akka.event.EventBus

实现转发器
object PartialEventBus {
  type ApplyEvent[E] = EventBus { type Event = E }
}

trait ForwardEventBus[E] extends EventBus { this : PartialEventBus.ApplyEvent[E] =>
  def relay : PartialEventBus.ApplyEvent[E]

  abstract override def publish(event : Event) : Unit = {
    relay.publish(event)
    super.publish(event)
  }
}

编译器需要ForwardEventBus的类型参数化才能将对象范围this.Event类型与外部relay.Event类型匹配。由于scala的路径依赖类型限制,编译器会在没有此类提示的情况下失败。

1 个答案:

答案 0 :(得分:0)

也许我很困惑,问题不应该是“为什么抽象覆盖会成功?”规范的第5.2.4节涵盖了abstract override,它说:“当与抽象修饰符结合使用时,覆盖修饰符具有额外的意义。该修饰符组合仅允许特征的值成员使用。”

我希望语言律师可以权衡,但看起来这不合法。