3

これらの 投稿に取り組んでいると、少なくともある程度は自己タイプを理解していると思いました。

そこで、期待どおりに失敗した例を作成しました。

scala> trait A { val v = "a" }
defined trait A

scala> trait B { this :A => ; var v = "" ; this.v = "b" }
<console>:6: error: reassignment to val
       trait B { this :A => ; var v = "" ; this.v = "b" }
                                                  ^

自己型の「これ」は、B の「これ」の影になっています。奇妙に見えますが、理にかなっています。

その場合、自己型に別の名前を付けるのが賢明に思えます。私はこれを行い、かなり驚いた:

scala> trait C { a :A => ; var v = "" ; this.v = "c" }
<console>:6: error: reassignment to val
       trait C { a :A => ; var v = "" ; this.v = "c" }
                                               ^

まだ陰になってる???

「ローカル」変数の名前を変更すると、物事がコンパイルされます。これは理にかなっています。

scala> trait D { a :A => ; var w = "" ; this.w = a.v }
defined trait D

(また、自己型名は、使用する「v」を明確にするためにオプションで使用できます。)

わかった。これは、以下が失敗することを意味しますか?

scala> trait E { this :A => ; var w = "" ; this.w = this.v }
defined trait E

は?これはどっち?:-(

それで... 自己型に名前を付ける意味はありますか? 「これ」は関係なく影になってしまうようです。

それとも、自己型の「this」が特性の「this」よりも優先されるスコープ規則のエッジケースですか?関連する特性に同じ名前を使用することは避けるべきですか?

4

2 に答える 2

8

あなたの問題は自己型の名前ではありません(すべての例で、代替自己型名の両方がまったく同じものを参照し、同じ型、つまり「およびthisの最大下限」[§5.1、Scala言語]を持っていますSpec]) しかし、明示的にオーバーライドせずに、同じ名前のフィールドを再度定義しようとします。BA

より簡単な例を見てください:

trait A { val v = "a" }
trait B { this: A =>
  var v = "b"
}

new A with B {} // does not compile

<console>:9: error: overriding value v in trait A$class of type java.lang.String;
 variable v in trait B$class of type java.lang.String needs `override' modifier
   new A with B {}

したがって、 を定義する際にエラーが発生することはありませんが、Bとにかく使用することはできません。

これはうまくいくでしょう

trait A { val v = "a" }
trait B { this:A => override val v = "b"  }

new A with B {}

ここでは、 inを明示的にオーバーライドしていAます。(は最後に来る必要があるため失敗することに注意してください。) また、ほとんどの場合、s を実際にオーバーライドすることはできず、.vBnew B with A {}Bvalvarvar

通常、これらの単純なケースでは、自己型の名前を気にする必要はありません。内に別の特性またはクラスを作成しない限りB、両方thisと、自己型変数と呼ぶものは同じものを指します。シャドーイングはありません。内に新しい特性があり、その特性内Bのインスタンスを参照する必要がある場合B、自己型に別の名前が必要になります。

このことを考慮

trait B { this =>
  val v = "b"
  trait C {
    val v = "c"
    println(this.v)
  }
  new C {}
}
new B {}

// prints c

対これ:

trait B { self =>
  val v = "b"
  trait C {
    val v = "c"
    println(this.v)  // prints c
    println(self.v)  // prints b
  }
  new C {}
}
new B {}

(これ以上の型注釈がなければthis、この例ではすべてを省略できます。)

于 2011-01-19T23:19:18.183 に答える
4

自己型はこれを隠していません。これのタイプです。(実際には、self-type は交差です: in trait A { self: B => ...} this の型は A と B です。) 複数の thises を明確にするための便宜として、self 型を指定するときに名前を指定できます。 、しかし、どのコード スニペットにもこれが複数あることはないため、無関係です。

[...] 自己型の「これ」が形質の「これ」よりも優先される場合

あなたはこれと同じ考えをいくつかの場所で持っています。これは複数あります。ありません。これしかありません。別のテンプレートを宣言するまで、別の this を取得することはありません。

trait A {
  self1 =>

  trait B {
    self2 =>

    // Here unqualified this refers to B and not A, so "self1" is useful.
    // ...but not necessary, because A.this.xxx does the same thing.
  }
}
于 2011-01-20T07:50:02.197 に答える