我想覆盖与性状抽象类型<:
并且不与=
(像答案这里Scala的上界:值不是类型参数中的一员 )。
我想用蛋糕图案,但这是不行的,我不明白为什么?
trait A {
def ping = println("ping")
}
trait Cake {
type T
}
trait S { this: Cake =>
type T = A
def t: T
t.ping
}
OK,这个例子中运行,但在我的实际使用情况下,我想重写型<:
而不是=
。它似乎是不可能的访问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成员,斯卡拉使用了两个规则:第一,混凝土始终覆盖抽象。 其次,如果两个成员都是混凝土,或在后来进来的线性化为了胜既抽象,那么一个。
此外,性状的自类型
trait S { this: C => ... }
隐式地扩充到
trait S { this: S with C => ... }
因此,在性状界说可以在S.访问你的情况,性状S被视为:
trait S { this: S with Cake =>
type T = A
def t: T
t.ping
}
现在,只要T是具体的,这是好的,因为它覆盖了抽象吨蛋糕。 但是,如果T是抽象的,那个在蛋糕中的线性顺序和胜后卡梅斯。 而那T没有上限,所以没有成员平。 解决这个问题的方法之一是通过写作来改变线性顺序:
trait S { this: Cake with S =>
type T <: A
def t: T
t.ping
}
如果斯卡拉有不同的规则,即抽象类型成员的所有约束中混入被合并,而不是根据线性化订单拣选一个成员,这将是更清洁。 这就是我们想在未来要考虑的改变,但我们需要小心的向后兼容性。
文章来源: Cake pattern with overriding abstract type don't work with Upper Type Bounds