1. 序章

Scalaのオブジェクトは、インスタンスが1つだけのクラスであり、他の場所でそれらを参照する場合にのみ遅延して作成されます。 オブジェクトはほぼどこにでも定義できますが、通常はトップレベルで定義します。 その場合、オブジェクトをシングルトンと呼ぶことができます。

シングルトンはグローバルに一意であり、JVM内で実行されているインスタンスは常に最大で1つです。

この記事では、Scalaでシングルトンオブジェクトを定義して使用する方法を見ていきます。

2. シングルトンの定義

トップレベルでobjectキーワードを使用して、シングルトンを定義できます。

object Counter {
  private var counter: Int = 0
  val label: String = "CounterLabel"

  def increment(): Unit = {
    counter += 1
  }

  def get: Int = counter
}

この場合、識別子 Counter は常に同じインスタンスを参照し、同様に、Counter.getは常に同じcounter整数を返します。 シングルトンは、他のすべてのScala オブジェクトと同様に、コンストラクターを持たないことに注意してください。

シングルトンオブジェクトは、追加の作業なしでScalaにシングルトンパターンを効果的に実装します。 前の例で示したように、メソッドだけでなく、可変状態と不変状態の両方を含めることができます。 ただし、可変状態が定義されている場合、シングルトンはデフォルトでスレッドセーフではありません。

3. シングルトンの使用

シングルトンは怠惰にインスタンス化されます。 たとえば、 Counter.get、Counter.label 、または Counter.increment()を呼び出すなど、オブジェクトを参照するまで、Counterのインスタンスは存在しません。ヒープ。 これらのメンバーの1つを参照するとすぐに、ランタイムはシングルトンの本体全体を実行します。 これは、 counter var label val を作成し、getincrementを定義することを意味しますメソッド。

Counterの例を実行してみましょう。

assert(Counter.get == 0)
assert(Counter.label == "CounterLabel")
Counter.increment()
assert(Counter.get == 1)
assert(Counter.label == "CounterLabel")

Counter.get の最初の呼び出し中に、ランタイムは counter 変数を作成し、それを0に設定します。 さらに、 label を作成し、「CounterLabel」に設定します。 次に、 Counter.increment()を呼び出して、可変状態を変更します。 最後に、 Counter.get を新たに呼び出すと、値が1になっているため、変更が行われたことが示されます。

Counter.counter は時間の経過とともに変化しますが、 Counter.label は不変であり、常に同じままです。 したがって、 assert(Counter.label ==“ CounterLabel”)は両方の時間で成功します。

Counter には可変状態が含まれているため、複数のスレッドが同時に使用すると競合状態が発生する可能性があります。

最後に、上記の例では、明示的にインスタンス化せずに、シングルトンの名前Counterのみを参照する必要があることに注意してください。

4. 結論

この簡単なチュートリアルでは、Scalaで状態とメソッドを使用してシングルトンオブジェクトを定義する方法を説明しました。 また、それを実験して、それを使用する方法と方法、そしてScalaがいつインスタンス化するかを学びました。

いつものように、完全なソースコードはGitHubにあります。