这在scala中有些出乎意料(或者我的期望是错误的)。以下是一些示例代码:
trait A
trait B
trait HasA { def foo: A }
trait HasB { def foo: B }
到目前为止很好,然后我做了
scala> trait HasBoth extends HasA with HasB
<console>:11: error: overriding method foo in trait HasA of type => A;
method foo in trait HasB of type => B has incompatible type
trait HasBoth extends HasA with HasB
好吧,我看到了错误。这说得通。
但是后面出现了混乱:
trait Wrapper[T] { def get: T }
trait HasBoth2 { self: Wrapper[HasA with HasB] => def bar = get.foo }
我觉得这很疯狂。如果我们检查bar
的类型,B
。如果我们翻转订单,使约束为HasB with HasA
,则bar
为A
。
所以我们在这里有些不一致。我希望其中任何一个:
HasA with HasB
自动生成{ def foo: A with B }
,或HasBoth2
会产生类型不兼容错误。请妥善解释这种不一致,或者它是一种类型系统错误。
更新
trait HasBoth3 extends HasA with HasB { def foo: A with B }
type Wrapped = Wrapper[HasBoth3]
Wrapped将满足HasBoth2的约束。
答案 0 :(得分:3)
这是预期的行为。这是斯卡拉的不健全的核心点之一。
SI-7278: Unsoundess in many guises
我在SI-7255中提供了一些解释,部分转载如下。
这似乎是类型系统的一个非常根本的失败,也许是dotty的动机的一部分。
抽象类型成员并不像通常所暗示的那样统一;他们只能被提炼。在这种情况下,这意味着创建一个类型,它是B与其自身类型的交集,即B与A的交集。交叉类型的创建假设它只能使用最后的C&#39;在线性化中,由于编译将在重新检查中失败,除非最后一个&#39; C&#39;是对任何早期版本的改进。
这个系统因自我类型而崩溃,因为一个类认为自己具有声明的类和声明的自身类型的交集。带有Y的X或带有X的Y可能是有效的实例化;没有先验的方法可以知道&#34; last&#34;成员C.
有关更多颜色,请参阅我对SI-7472的最新评论。