scala> class A
defined class A
scala> class B {this: A => }
defined class B
scala> new B
<console>:10: error: class B cannot be instantiated because it does not conform
to its self-type B with A
new B
^
类B
将self类型设置为类A
,因此类B
(或其子类)必须扩展类A
以创建{的实例{1}}。但这是否可行,因为B
的子类只能扩展一个类(这是类B
)?
所以这引出了我的问题,在任何情况下将类的自我类型声明为另一个类是否有意义?
答案 0 :(得分:10)
你认为这个定义不能导致具体的实现是正确的,因为你不能混合两个类,只有特征。所以简短的回答是'不',或者应该是一个特征。
关于自我类型,Stackoverflow有几个问题。这两个有用的是:
在第二个问题中,Ben Lings给出了一个很好的答案,他引用了Spiros Tzavellas博客中的以下段落:
总之,如果我们想在特征中移动方法实现,那么我们冒险使用支持具体方法的实现的抽象方法来污染这些特征的接口,并且与特征的主要责任无关。这个问题的解决方案是将这些抽象方法移动到其他特征中,并使用自我类型注释和多重继承将这些特征组合在一起。
例如,如果A
(假设它是特征而不是现在的类!)是一个记录器。您不希望B
公开A
混合的日志记录API。因此,您将使用自我类型而不是mixin。在B
的实现中,您可以调用日志API,但是从外部看不到它。
另一方面,您可以使用以下形式的构图:
trait B {
protected def logger: A
}
现在的区别在于
B
在想要使用其功能时必须引用logger
B
的子类型可以访问logger
B
和A
不会在命名空间中竞争(例如,可以使用相同名称的方法而不会发生冲突)我想说自我类型是Scala的一个相当外围的特性,在很多情况下你不需要它们,并且你有这样的选项来实现几乎没有自我类型。