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 のメンバーではありません

extendsself 型の代わりに を使用すると、正常にコンパイルされます。

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
}

あなたは2つのことをしています

  • thisとして扱う必要があることをコンパイラに伝えますBase(これは次のように定義attributeされます)AttributeBase
  • attributeに特化Attribute

では、どちらが優先されますか?

Scala 2.13 仕様では、自己型の定義を特定できませんでした。AFAIK では、構文の要約として、SelfTypeまたは変更ログにしか存在しません。型割り当てを (おそらくエイリアス化された) で呼び出す非公式な方法のようです (this型割り当てと型定義に関するすべての通常の規則に従っているため、特別な処理はなく、明示的に対処する必要はありません)。もしそうなら、自己型についてScala のツアーで読んだことに従うかもしれません- 内部のすべての定義の POV からself: Tpe =>一種のキャスト(絞り込み) をthis行いTpeますが、同時に新しい定義の追加と既存の定義の特殊化を可能にします (そのため、2.13 は、お気づきのように一貫性がありません)。

Scala 3では、(選択的な)型キャストではなく、型結合として扱うように見えるため、より適切に整理されているようです ( Scala 3 が DOT 計算を実装し、矛盾とあいまいさを取り除こうとしていることを考えると、これは理にかなっています)。ただし、仕様の自己型に関する正確な記述も見つけることができなかったので、この改善は、より良い形式主義に従うことの「単なる」副作用である可能性があると言えます。

于 2021-11-26T13:46:37.063 に答える