具有覆盖抽象类型的蛋糕模式不适用于类型上限 [英] Cake pattern with overriding abstract type don't work with Upper Type Bounds
问题描述
我想用 <:
而不是 =
覆盖 trait 中的抽象类型(就像这里的答案 Scala 上限:值不是类型参数的成员).
I want to override abstract type in trait with <:
and not with =
(like answer here Scala Upper Bounds : value is not a member of type parameter).
我想使用蛋糕图案,但这不起作用,我不明白为什么?
I want to use cake pattern, but this doesn't work, i don't understand why ?
trait A {
def ping = println("ping")
}
trait Cake {
type T
}
trait S { this: Cake =>
type T = A
def t: T
t.ping
}
好的,这个例子运行了,但在我的实际用例中,我想用 <:
而不是 =
覆盖类型.似乎不可能访问 t功能,为什么?
OK, this example run, but in my real use case i want to override type with <:
and not with =
.It seems impossible to access the t function, why ?
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 使用两条规则:首先,具体总是覆盖抽象.其次,如果两个成员都是具体的,或者都是抽象的,那么以线性化顺序出现在后面的那个会获胜.
It's a shortcoming of Scala's type system. When determining the members in a mixin, Scala uses two rules: First, concrete always overrides abstract. Second, If two members are both concrete, or both abstract, then the one that comes later in linearization order wins.
此外,特征的自我类型
trait S { this: C => ... }
被隐式扩充为
trait S { this: S with C => ... }
这样就可以在 S 中访问 trait S 中的定义.在你的例子中,trait S 被视为:
so that definitions in the trait S can be accessed within S. In your case, the trait S is seen as:
trait S { this: S with Cake =>
type T = A
def t: T
t.ping
}
现在,只要 T 是具体的就可以了,因为它覆盖了 Cake 中的抽象 T.但是如果 T 是抽象的,则 Cake 中的那个在线性化顺序中排在后面并获胜.而且那个 T 没有上限,所以没有成员 ping.解决此问题的一种方法是通过编写以下内容更改线性化顺序:
Now, as long as T is concrete this is fine because it overrides the abstract T in Cake. But if T is abstract, the one in Cake cames later in the linearization order and wins. And that T does not have an upper bound, so no member ping. One way to fix this is to change the linearization order by writing:
trait S { this: Cake with S =>
type T <: A
def t: T
t.ping
}
如果 Scala 有一个不同的规则,即抽象类型成员的所有约束都合并到 mixin 中,而不是根据线性化顺序选择单个成员,那将会更清晰.这是我们将来要考虑的更改,但我们需要注意向后兼容性.
It would be cleaner if Scala had a different rule that says that all constraints of abstract type members are merged in the mixin, instead of picking a single member according to linearization order. That's a change we want to consider in the future, but we need to be careful with backwards compatibility.
这篇关于具有覆盖抽象类型的蛋糕模式不适用于类型上限的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!