Scala中类主体中的右箭头

Cha*_*les 7 scala

浏览Scala源代码,我偶然发现Enumeration.scala:

abstract class Enumeration(initial: Int, names: String*) extends Serializable {
  thisenum =>

  def this() = this(0)
  def this(names: String*) = this(0, names: _*)    

  /* Note that `readResolve` cannot be private, since otherwise
     the JVM does not invoke it when deserializing subclasses. */
  protected def readResolve(): AnyRef = thisenum.getClass.getField("MODULE$").get()

  // ... SNIP ...

}
Run Code Online (Sandbox Code Playgroud)

有什么thisenum =>用?我在"Scala编程"一书中找不到任何信息.

Von*_*onC 8

Scala 2d编程中的编程在第29.4节"将模块拆分为特征"一节中介绍了自我类型的概念:

SimpleFoods特征可能看起来像:

trait SimpleFoods {
  object Pear extends Food("Pear")
  def allFoods = List(Apple, Pear)
  def allCategories = Nil
}
Run Code Online (Sandbox Code Playgroud)

到目前为止一直很好,但不幸的是,如果你试图定义一个像这样的SimpleRecipes特征,就会出现问题:

trait SimpleRecipes { // Does not compile
  object FruitSalad extends Recipe(
    "fruit salad",
    List(Apple, Pear), // Uh oh
    "Mix it all together."
  )
  def allRecipes = List(FruitSalad)
}
Run Code Online (Sandbox Code Playgroud)

这里的问题是与Pear使用它的特性不同,因此它超出了范围.
编译器不知道SimpleRecipes只与它混合在一起SimpleFoods.
但是,有一种方法可以告诉编译器.Scala为这种情况提供了自我类型.
从技术上讲,无论何时在类中提到,自我类型都是假定的类型.
实际上,self类型指定了特征混合到的任何具体类的要求.
如果您有一个仅在与其他特征或特征混合时使用的特征,那么您可以指定应该假设其他特征.
在目前的情况下,指定一个自我类型就足够了SimpleFoods,如图所示:

trait SimpleRecipes {
  this: SimpleFoods =>
  object FruitSalad extends Recipe(
    "fruit salad",
    List(Apple, Pear), // Now Pear is in scope
    "Mix it all together."
  )
  def allRecipes = List(FruitSalad)
}
Run Code Online (Sandbox Code Playgroud)

鉴于新的自我类型,Pear现在可用.
隐含地,引用Pear被认为是this.Pear.
这是安全的,因为混入的任何具体类SimpleRecipes也必须是子类型SimpleFoods,这意味着Pear它将是一个成员.
抽象的子类和特征不必遵循此限制,但由于它们无法使用new进行实例化,因此不存在this.Pear引用失败的风险


Dan*_*ral 3

这是一种自我类型。请参阅《Scala 编程》第二版第 29.4 节。我认为第一版中没有涉及到它,而且我也没有可以查找的内容。

在这个例子中,所做的就是确保从 的任何内部thisenum引用Enumeration's 。thisEnumeration