3

私のゲームには、次のような Sounds オブジェクトがあります。

object Sounds {
  SoundFactory.setAssetBasePath("mfx/")

  val EXPLOSION_0 = ESound("explosion1.ogg")
  val EXPLOSION_1 = ESound("explosion2.ogg")
  val EXPLOSION_2 = ESound("explosion3.ogg")
  val IMPACT_0 = ESound("impact1.ogg", 0.4f)
  val IMPACT_1 = ESound("impact2.ogg", 0.4f)
  val IMPACT_2 = ESound("impact3.ogg", 0.4f)
  val BONUS = ESound("bonus.ogg", 0.7f)

  // -- snip --

  def load() {
    println("Sounds loaded")
  }

  case class ESound(sound_file: String, volume: Float = 1) {
    private val sound = SoundFactory.createSoundFromAsset(AndEngine.engine.getSoundManager, AndEngine.activity.get, sound_file)
    sound.setVolume(volume)
    sound.setLoopCount(0)

    def play() { sound.play() }
  }
}

簡潔にするために、多くのメソッドなどを削除しました。しかし、基本的な考え方は、Scala はオブジェクトを遅延して初期化するというものでした。そのためload()、このオブジェクトでメソッド ( ) を初めて呼び出すと、初期化されます。これは、たとえばテクスチャのロードなどの後に行われます。

しかし、上記のコードでは、ゲームでメニュー ボタンを初めて押すと、(SoundFactory.createSound...コンストラクターの によって) すべてのサウンドが読み込まれるため、長い一時停止が発生します。

loadメソッドを次のように変更すると、次のようになります。

    println("Sounds loaded, " + BONUS.toString)

すべてのサウンドが正しくロードされます。

それで、なぜこれが起こるのですか?Scala はどのように Sounds オブジェクトを初期化するので、load() を呼び出すことができますが、コンストラクター部分で独自の値をロードしませんか? コンパニオン オブジェクトの初期化の規則は何ですか?

4

1 に答える 1

6

Scala仕様のセクション5.4によると:

オブジェクト定義によって定義された値は遅延してインスタンス化されることに注意してください。新しい m$cls コンストラクターは、オブジェクト定義の時点では評価されませんが、代わりに、プログラムの実行中に m が初めて逆参照されたときに評価されます (まったく実行されない可能性があります)。コンストラクターの評価中に m を再度逆参照しようとすると、無限ループまたは実行時エラーが発生します。コンストラクターの評価中に逆参照を試みる他のスレッドは、評価が完了するまでブロックされます。

コンパニオン オブジェクトは、最初に参照されたときに構築する必要があります。これは、あなたの理解でもあると思います。これは、次の例で機能します。

object Sounds {
  val EXPLOSION_0 = ESound("EXPLOSION_0")
  def load() { println("loaded") }
  case class ESound(file: String) {
    private val sound = {
      println("waiting 1s before loading " + file)
      Thread.sleep(1000)
      "sound from " + file
    }
  }
}

object C extends App {
  Sounds.load()
}

版画:

[info] Running C
waiting 1s before loading EXPLOSION_0
loaded

したがって、予期しない動作は、投稿していないセクションに起因する可能性があります。

于 2012-02-25T13:52:34.437 に答える