web-dev-qa-db-ja.com

特性を持つ匿名クラスの初期化

誰かが次の行動を理解するのを手伝ってくれませんか?

簡単に言えば、次の2つのケースの違いは何ですか...

単純なクラスc +特性tを定義します

scala> class c {val x=true; val y=this.x} 
defined class c

scala> trait t {}
defined trait t

新しい「c with t」をインスタンス化できます

scala> new c with t
res32: c with t = $anon$1@604f1a67

しかし、新しい「[cのような匿名クラス]をtでインスタンス化する」ことはできません。

scala> new {val x=true; val y=this.x} with t
<console>:9: error: type mismatch;
 found   : type
 required: ?{def x: ?}
<console>:9: error: value x is not a member of object $iw
              new {val x=true; val y=this.x} with t

これら2つのケースの違いは何ですか?

ありがとう!

22
Bosh

「早期定義」構文に遭遇しました( 詳細 )。

言語仕様のセクション5.1.6を確認してください。

初期定義は、テンプレートが定義される直前に有効なスコープで型チェックおよび評価され、包含クラスの型パラメーターおよび定義されているものの前の初期定義によって拡張されます。特に、初期の定義の右側にあるthisへの参照は、テンプレートのすぐ外側のthisのIDを指します。 そのため、同じセクション内の他の先行する初期定義を除き、初期定義がテンプレートによって構築されるオブジェクトを参照すること、またはそのフィールドとメソッドの1つを参照することは不可能です。

あなたの場合、問題はthis.xにあります。これをxだけで置き換えると、上記の最後の文で述べた「前の初期定義」を参照している(@ som-snyttに感謝します)と、コンパイルされます。

もちろん、おそらく初期のイニシャライザを書くつもりはなかったので、クリスチャン・ドマガラの答えに従って書いてください。

5
Luigi Plinge

これはあなたが求めているものですか?

new t {val x=true; val y=this.x}

別の特性がある場合は、u {}、 あなたは書ける new t with u {val x=true; val y=this.x}

28