4

以下代码无法使用 Scala 2 编译(测试 2.13.7 和 Scala 2.12.15):

trait AttributeBase

trait Attribute extends AttributeBase {
  def name: String
}

trait Base {
  def attribute: AttributeBase
}

trait Derived { self: Base =>
  
  def attribute: Attribute
  
  def name = attribute.name
}

该代码可以使用 Scala 3 编译。使用 Scala 2 的错误是:

值名称不是 AttributeBase 的成员

extends当使用而不是 self 类型时,它编译得很好:

trait Derived extends Base {

另一种可能的解决方法是:

  def name = (this:Derived).attribute.name

为什么Derived.attributed假定的类型是AttributeBase而不是Attribute?这是 Scala 编译器错误,还是某些 Scala 2 限制?

4

1 回答 1

3

我会说这将是一个错误,或者在解释自我类型时至少是 2 和 3 之间的差异。这里:

trait Derived { self: Base =>
  
  def attribute: Attribute
}

你在做两件事

  • 告诉编译器this应该被视为Base(定义attributeAttributeBase
  • 专门attribute作为Attribute

那么哪个优先呢?

在 Scala 2.13 规范中,我无法确定自类型的定义,AFAIK 它仅存在于语法摘要中SelfType或更改日志中。这似乎只是一种调用类型归属的非正式方式(可能是别名)this(遵循关于类型归属和类型定义的所有正常规则,因此没有特殊处理,因此无需明确解决)。如果是这样,它可能会遵循我们在Tour of Scala中读到的关于自类型的内容——从内部所有定义的 POV 中进行self: Tpe =>某种强制转换(缩小),但同时允许添加新定义并专门化现有定义(所以 2.13 有点像你注意到的不一致)。thisTpe

似乎 Scala 3 对其进行了更好的整理,因为它似乎将其视为类型绑定而不是(选择性)类型转换(考虑到 Scala 3 实现了 DOT 演算并试图消除不一致和歧义,这是有道理的)。但是,我也无法在规范中找到关于自我类型的确切陈述,所以我会说这种改进可能“只是”遵循更好的形式主义的副作用。

于 2021-11-26T13:46:37.063 回答