我想用 <:
覆盖特征中的抽象类型而不是 =
(就像这里的回答 Scala Upper Bounds : value is not a member of type parameter )。
我想使用蛋糕图案,但这不起作用,我不明白为什么?
trait A {
def ping = println("ping")
}
trait Cake {
type T
}
trait S { this: Cake =>
type T = A
def t: T
t.ping
}
好的,这个例子运行了,但在我的实际用例中,我想用
<:
覆盖类型而不是与 =
. 似乎无法访问 t 函数,为什么?trait S { this: Cake =>
type T <: A
def t: T
t.ping
}
返回错误
value ping is not a member of S.this.T
最佳答案
这是 Scala 类型系统的一个缺点。在确定 mixin 中的成员时,Scala 使用两条规则:首先,具体总是覆盖抽象。其次,如果两个成员都是具体的,或者都是抽象的,那么以线性化顺序出现在后面的那个会获胜。
此外,特质的自我类型
trait S { this: C => ... }
被隐式扩充为
trait S { this: S with C => ... }
这样就可以在 S 中访问 trait S 中的定义。在你的情况下,trait S 被视为:
trait S { this: S with Cake =>
type T = A
def t: T
t.ping
}
现在,只要 T 是具体的,这很好,因为它覆盖了 Cake 中的抽象 T。但是如果 T 是抽象的,则 Cake 中的那个在线性化顺序中排在后面并获胜。而且那个 T 没有上限,所以没有成员 ping。解决此问题的一种方法是通过编写以下内容来更改线性化顺序:
trait S { this: Cake with S =>
type T <: A
def t: T
t.ping
}
如果 Scala 有一个不同的规则,即抽象类型成员的所有约束都合并到 mixin 中,而不是根据线性化顺序选择单个成员,那将会更清晰。这是我们将来要考虑的更改,但我们需要注意向后兼容性。
关于scala - 具有覆盖抽象类型的蛋糕模式不适用于类型上限,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10213395/