引用类型参数的抽象类型成员
Referring abstract type member of a type parameter
我的场景是这样的:
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())
这有什么问题吗?以及(如果可能的话)如何更正此代码?
D#B
是类型投影,与 d.B
不同。您有类型不匹配,因为在 foo
中,B
实际上意味着 this.B
,这与 D#B
不同(后者更通用)。
非正式地,您可以将 D#B
视为表示抽象类型 B
可以为 D
的任何实例采用的任何可能类型,而 d.B
是 [=15] 的类型=] 对于特定实例 d
.
有关某些上下文,请参阅 What does the `#` operator mean in Scala? and What is meant by Scala's path-dependent types?。
编译它的一种方法是将 createB
的 return 类型更改为 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)
}
}
更新 给定我不确定这是否应该被视为一个错误
这是一个错误: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
}
}
这看起来像是实现泄漏。有一个解决方法涉及转换为交叉类型(危险,转换错误等;请参阅我的其他答案 )
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!
}
}
我的场景是这样的:
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())
这有什么问题吗?以及(如果可能的话)如何更正此代码?
D#B
是类型投影,与 d.B
不同。您有类型不匹配,因为在 foo
中,B
实际上意味着 this.B
,这与 D#B
不同(后者更通用)。
非正式地,您可以将 D#B
视为表示抽象类型 B
可以为 D
的任何实例采用的任何可能类型,而 d.B
是 [=15] 的类型=] 对于特定实例 d
.
有关某些上下文,请参阅 What does the `#` operator mean in Scala? and What is meant by Scala's path-dependent types?。
编译它的一种方法是将 createB
的 return 类型更改为 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)
}
}
更新 给定
这是一个错误: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
}
}
这看起来像是实现泄漏。有一个解决方法涉及转换为交叉类型(危险,转换错误等;请参阅我的其他答案
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!
}
}