16

我有一个trait,它接受一个类型参数,我想说实现这个trait的对象也会符合这个类型参数(使用泛型,为了Java的兼容性)

以下代码:

trait HandleOwner[SELF <: HandleOwner[SELF]] {
self : SELF =>
    // ...
    def handle: Handle[SELF]
}

trait Common[SELF <: Common[SELF]]  extends HandleOwner[SELF] {
    // ...
}

给我以下错误:

illegal inheritance;  self-type test.Common[SELF] does not conform to
test.HandleOwner[SELF]'s selftype SELF

如果我将 Common 更改为:

trait Common[SELF <: Common[SELF]]  extends HandleOwner[SELF] {
self : SELF =>
    // ...
}

然后错误消失。

为什么我必须在每个非具体类型中重复相同的声明。如果我有一个基类,并说“扩展 Comparable”,我不必在每个派生类型中重复“扩展 Comparable”,只要具体类实现 compareTo 方法。我想这里应该是一样的。我只是说扩展 HandleOwner 的类型也是SELF,编译器应该接受它,并考虑它,而不需要每个非具体子类型再次重复相同的事情。

A 这样做是为了避免必须使用类转换,但我将从字面上扩展这个特性的每个类,我不认为我应该重复这个声明数百甚至数千次!

4

1 回答 1

16

自类型更类似于通用约束而不是继承。使用class C[A <: B],约束必须在子类中一直重复:class D[A <: B] extends C[A]. 必须重复约束,直到它被满足,也就是说,直到您选择了一个确实满足的实际参数类型<: B。self 类型也一样。写作self: A =>不会让你的类型扩展A。它确保它最终必须在实际实例化之前与 A 混合。

相反,当您扩展时Comparable,您已经创建了您的类 a Comparable,而不是为以后设置约束。但是你需要实现的事实compareTo仍然需要一直重复,abstract直到你真正实现它。

当然,编译器可以不重复<: B,self: A =>abstract,信息可用。这是语言设计者的选择。至少,必须重复self: A =>与其他地方的规则没有什么不同。

于 2011-09-11T15:28:15.610 回答