此问题遵循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
^
有什么问题?
答案 0 :(得分:1)
def control(c: =>T): T
返回类型S#T
。显然,c
也有T
类型。因此,返回c
:
def control(c: =>T): T = c
编译,而返回c.s
则无法编译,因为s
的返回类型为Unit
。
c.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
表示我们想要的确切内容。