6
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
             ^

ClassB将 self 类型设置为 class A,因此 class B(或其子类)必须扩展 classA以创建B. 但这有可能吗,因为一个子类B只能扩展一个类(这是 class B)?

所以这让我想到一个问题,在任何情况下将一个类的 self 类型声明给另一个类是否有意义?

4

1 回答 1

10

你的观察是正确的,这个定义不能导致具体的实现,因为你不能混合两个类,只有特征。所以简短的回答是“不”,两者都应该是一个特征。

Stackoverflow 上有几个关于自我类型的问题。这些是两个有用的:

在第二个问题中,Ben Lings 给出了一个很好的答案,他引用了Spiros Tzavellas博客中的以下段落:

总之,如果我们想将方法实现移动到 trait 中,那么我们就有可能用支持具体方法实现并且与 trait 的主要职责无关的抽象方法污染这些 trait 的接口。解决这个问题的方法是将这些抽象方法移动到其他特征中,并使用自类型注释和多重继承将这些特征组合在一起。

例如,如果A(假设它现在是一个特征而不是一个类!)是一个记录器。您不想B公开公开混入A. 因此,您将使用 self 类型而不是 mixin。在实现中,B您可以调用日志记录 API,但从外部看是不可见的。


另一方面,您可以使用以下形式的组合:

trait B {
    protected def logger: A
}

现在的不同是

  • Blogger想使用其功能时必须参考
  • 的子类型B可以访问logger
  • B并且A不要在命名空间中竞争(例如,可以有同名的方法而不会发生冲突)

我想说自类型是 Scala 的一个相当外围的特性,在很多情况下您不需要它们,并且您可以选择这样的选项来实现几乎相同的目标,而无需自类型。

于 2012-06-30T12:50:18.540 回答