这在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的约束。
这是预期的行为。它是scala不稳定的核心点之一。
SI-7278:
我在SI-7255中提供了一些解释,转载于下文部分。
这似乎是类型系统的一个相当根本的失败,可能也是多蒂的部分动机
抽象类型的成员并不像这个词通常暗示的那样统一;它们只能被提炼。在这种情况下,这意味着创建了一个类型,它是B与其自身类型的交集,也就是说,B与a的交集。创建交集类型时假设它只能在线性化中使用最后一个"C",因为除非最后的"C"是任何早期"C"的精化,否则编译将在refcheck中失败
这个系统因self-type而崩溃,因为类将自己视为具有声明类和声明self-type的交集。X与Y或Y与X可能是有效的实例化;没有办法先验地知道哪一个是"最后一个"成员C。
有关更多颜色,请参阅我对SI-7472的最后一条评论。