我的情景如下:
trait A {
type B
def foo(b: B)
}
trait C[D <: A] {
val d: D
def createB(): D#B
def bar() {
d.foo(createB)
}
}
在REPL中,它抱怨
<console>:24: error: type mismatch;
found : D#B
required: C.this.d.B
a.bar(createB())
这有什么问题?并且(如果可能的话)如何更正此代码?
答案 0 :(得分:3)
D#B
是一种类型投影,与d.B
不同。您的类型不匹配,因为在foo
中,B
实际上意味着this.B
,其中所述与D#B
不同(后者更为一般)。
非正式地,您可以将D#B
视为表示抽象类型B
可以为D
的任何实例采用的任何可能类型,而d.B
是B
的类型对于特定实例d
。
有关某些情况,请参阅What does the `#` operator mean in Scala?和What is meant by Scala's path-dependent types?。
将其编译为一种方法是将createB
的返回类型更改为d.B
:
def createB(): d.B
然而,在许多情况下,这样的解决方案限制性太强,因为您绑定到特定实例d
,这可能与您的想法不同。
另一种解决方案是用类型参数替换抽象类型(尽管它更详细):
trait A[B] {
def foo(b: B)
}
trait C[B, D <: A[B]] {
val d: D
def createB(): B
def bar() {
d.foo(createB)
}
}
答案 1 :(得分:1)
更新 给定this answer我不确定这是否应被视为错误
这是一个错误:SI-4377。显式类型归属产生
trait C[D <: A] {
val d: D
def createB(): D#B
def bar() {
(d:D).foo(createB)
// [error] found : D#B
// [error] required: _3.B where val _3: D
}
}
看起来像实施泄漏。有一种解决方法,涉及投射到交叉点类型(危险,铸造错误等;请参阅我的其他答案here)
trait A {
type B
def foo(b: B)
}
case object A {
type is[A0 <: A] = A0 {
type B = A0#B
}
def is[A0 <: A](a: A0): is[A0] = a.asInstanceOf[is[A0]]
}
trait C[D <: A] {
val d: D
def createB(): D#B
def bar() {
A.is(d).foo(createB) // use it here!
}
}