3

混合する特性の前に初期化する必要がある匿名クラスがあります。「this」参照の使用が許可されていないため、早期初期化は機能しません。クラスを self 型の内部トレイトとして宣言すれば機能させることができますが、この型はコード内の 1 か所でしか使用されず、匿名クラスとしてインライン化するのは直感的であるため、これは不必要に冗長に思えます。ただし、scala が受け入れ、私が持っている初期化順序の要件を満たす構文を見つけたようです。これは余分な詳細を除いた単純化された例です (私がこのようにする理由があると仮定します)。

trait WaitCondition[+T] {
...
}

trait EventWaitCondition[+T] extends WaitCondition[T] {
...
}

trait Event { outer =>
    private[this] var _cachedWaitCondition : Option[WaitCondition[T]]

    def next() : WaitCondition[T] =
        //Is there a way to "inline" the defintion of NextWaitCondition
        //without screwing up the initialization order?
        _cachedWaitCondition.getOrElse{ new NextWaitCondition with EventWaitCondition[T] }

    private[this] trait NextWaitCondition { this : WaitCondition[T] =>
        outer._cache = Some(this)
        ....
    }
    ....
}

したがって、基本的に、私の質問は、NextWaitCondition と WaitCondition の間の初期化順序を変更せずに (つまり、NextWaitCondition が最初に初期化されるように)、匿名型として NextWaitCondition の定義をインライン化する方法があるということです。

4

3 に答える 3

1

短い答え: もちろん違います。

初期化順序の法則を曲げるには正当な理由があるというあなたの言葉を受け入れなければなりません。律法を尊重しながらもその下で苦しんでいる魂について少し考えてみてください。

@xiefeiの答えは不器用ではありません。それはあなたが求めるクラッジに影響を与えるのに十分に構造化されています.

postConstructor フックを支持して DelayedInit を廃止するという話があります。しかし、あなたは本当に preConstructor フックを求めているので、それをテンプレート メソッドで形式化してみませんか?

また、Foo と SubFoo の間の依存関係によっては、これは継承よりも構成を優先する問題になる可能性があります。次に、初期化順序を持つゲームはありません。

以下では、まず、名前付きソリューションをテンプレート メソッドで一般化します。使用するサイトだけがそれを知っている、または気にかけているという利点があります。

trait Second {
  println("I must happen after first.")
}
trait SecondDelayed extends DelayedInit {
  println("SecondDelayed neutral stuff")
  def delayedInit(body: =>Unit) {
    body // body first
    println("I must be delayed after first.")
  }
}
trait Firstly {
  def firstly
  firstly
}

object Test extends App {
  def trial(t: =>Unit) {
    println("----")
    t
  }
  // candidate for least obnoxious
  trial {
    new Firstly with Second {
      def firstly {
        println("Do this firstly.")
      }
      println("Don't care when this happens.")
    }
  }
  trial {
    // current solution
    new Something with Second
    trait Something { this: Second =>
      println("First code.")
    }
  }
  trial {
    // prefer anon
    new Second {
      println("Anon first?") // nope
    }
  }
  trial {
    // DelayedInit solution
    new SecondDelayed {
      println("Anon first, then other delayed.")
    }
  }
  trial {
    // the "delayed" code must be idempotent,
    // or find a useful way to trigger execution;
    // here, the delayed code happens twice.
    class Foo extends SecondDelayed {
      println("Foo wants init, too")
    }
    new Foo {
      println("Anon first, then other delayed.")
    }
  }
  /* early defs are only for defs, with no this
  new {
    println("Anon first.")
  } with Second
  */
  trial {
    // trait code doesn't participate
    new DelayedInit with Second {
      def delayedInit(body: =>Unit) {
        println("My crucial early init business")
        body
      }
    }
  }
}
于 2012-11-27T17:32:08.020 に答える
1

DelayedInitこれがあなたの望むものかどうかはわかりませんが、特性が役立つかもしれません。

trait WaitCondition[+T]

trait EventWaitCondition[+T] extends WaitCondition[T] with DelayedInit{
  def delayedInit(body: => Unit) = {
    body
    println("Initializing EventWaitCondition...")
  }
}

trait Event[T] { outer =>
  var _cachedWaitCondition: Option[WaitCondition[T]] = None
  var _cache: Option[WaitCondition[T]] = None

  def next(): WaitCondition[T] = _cachedWaitCondition.getOrElse(new EventWaitCondition[T] {
        println("Initializing NextWaitCondition...")
        outer._cache = Some(this)
      })
}

new Event[Int]{} next                           

//> Initializing NextWaitCondition...
//| Initializing EventWaitCondition...

このアプローチの欠点は、後bodyに配置される初期化コードdelayedInitが常に遅延することです。

于 2012-11-26T08:25:15.523 に答える
0

これが完全に間違っている/不適切である場合はお知らせください。

def next() : WaitCondition[T] = _cachedWaitCondition.getOrElse{ 
    new {
      outer._cache = Some(this)
    } with NextWaitCondition with EventWaitCondition[T]
  }

ここで私が理解している限り、outer._cache何かがそれを使用する前に初期化される限り、必ずしも初期化順序をいじる必要はありません。

于 2017-10-18T07:03:55.667 に答える