具有覆盖抽象类型的蛋糕模式不适用于上部类型边界 [英] Cake pattern with overriding abstract type don't work with Upper Type Bounds
问题描述
我想用<:
覆盖trait中的抽象类型,而不是用 =
(如在这里回答< a href =http://stackoverflow.com/questions/9217918/scala-upper-bounds-value-is-not-a-member-of-type-parameter> 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
}
OK,这个例子运行,但是在我真正的用例中,我想用<:
重写类型,而不是使用 =
。似乎不可能访问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
}
返回错误值ping不是S.this.T的成员
推荐答案
这是Scala类型系统的一个缺点。当确定混合中的成员时,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中可以访问特征S中的定义。在您的情况下,特征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 Came中的一个在线性化顺序中获胜。而且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屋!