7

If I write :

trait T {
  val t = 3
  val u = 1::t::Nil
}

class U extends T {
  override val t = 2
}

(new U).u

it shows this.

List(1, 0)

How should I change the above code to make it display the following:

List(1, 2)

i.e. override val t sets the value of t for u in the trait T?

4

3 に答える 3

12

これを行う 1 つの方法は、次のようにoruを使用しての評価を遅らせることです。deflazy val

trait T {
  def t = 3
  def u = 1::t::Nil
}

class U extends T {
  override def t = 2
}

(new U).u

また

trait T {
  val t = 3
  lazy val u = 1::t::Nil
}

class U extends T {
  override val t = 2
}

(new U).u 

違いは次のとおりです。

  • val初期化中に式を評価させます
  • defuが使用されるたびに式を評価させます
  • lazy val最初の使用時に評価しu、結果をキャッシュします
于 2013-04-02T11:38:34.280 に答える
10

初期イニシャライザを使用してみてください:

scala> trait T {
     |   val t = 3
     |   val u = 1::t::Nil
     | }
defined trait T

scala> class U extends {
     | override val t = 2;
     | } with T
defined class U

scala> (new U).u
res1: List[Int] = List(1, 2)

早期初期化の詳細については、たとえばこちらを参照してください。

于 2013-04-02T11:44:47.773 に答える
4

すべての scala 宣言型スタイルは単なる幻想です。Scala は jvm 上に構築され、java のように動作します。

Evetything はクラスであり、その使用法に依存する必要はありません (Java は C++ ではなく、長所と短所を備えたインクリメンタル ビルドをサポートしています)。すべての特性には独自の初期化コードがあり、マルチ特性クラスはそれぞれの初期化コードを 1 つずつ実行します。サブクラスでのみ宣言されている AnyRef を使用すると、その値は初期化中に null に設定されます。

私は特定の規約規則で身を守ります: すべての val は final または lazy のいずれかでなければなりません (非 final クラスで単純な val を使用する理由) 。そのため、初期化の順序は気にせず、さらに宣言型言語を使用しているふりをすることがあります。

また、オプションを使用しています-Xcheckinit:フィールドアクセサーにランタイムチェックを追加します。

于 2013-04-02T13:13:10.317 に答える