覆盖抽象类型不适用于控件抽象

时间:2013-01-10 13:26:25

标签: scala traits abstract-type

此问题遵循Cake pattern with overriding abstract type don't work with Upper Type Bounds中的问题。我想用<:覆盖trait中的抽象类型。前面的链接提供了解决方案,其中包括通过在特征S中写入this: Cake with S来更改线性化的顺序。但是,我在以下代码中添加了名为control的控件抽象。我想在其中调用方法t

trait A {
  def ping = println("ping")
}

trait Cake {
  type T
}

trait S { this: Cake with S =>
  type T <: A with S
  def t: T
  def s = println("test")
  // def control(c: =>T): T = c // compile
  // def control(c: =>T): T = c.s // does not compile
  def control(c: =>T): T = c.t // does not compile
  t.ping
  t.s
}

但是,此代码导致编译错误,我无法解释

 found   : S.this.T#T
 required: S.this.T
         def control(c: =>T): T = c.t
                                    ^

有什么问题?

1 个答案:

答案 0 :(得分:1)

def control(c: =>T): T

返回类型S#T。显然,c也有T类型。因此,返回c

def control(c: =>T): T = c

编译,而返回c.s则无法编译,因为s的返回类型为Unitc.t无法编译,因为它的返回类型为S#T#T

因此,以下将编译:

def control(c: =>T): T#T = c.t

由于这里发生的所有事情背后的细节通常有点不重要,我建议你谷歌“类型投影”和“路径依赖类型”获取更多信息。

基本上发生的事情c的类型为T,其中T <: A with S,所以我们知道T必须包含所有S个成员,一个其中定义为def t: T。但是这个T不一定与我们的T相同,所以当我们在您的示例中调用c.t时,它不符合。我们想要的是T T类型T(或同等地,T的{​​{1}},或类型成员T的{​​{1}} )。这里T表示我们想要的确切内容。