web-dev-qa-db-ja.com

Scalaでコンパニオンオブジェクトを持つ背後にある理由は何ですか?

クラスのコンパニオンオブジェクト(シングルトン)が必要な場合はありますか?なぜFooと言うクラスを作成し、そのクラスのコンパニオンオブジェクトも作成するのですか?

100
Rahul

コンパニオンオブジェクトは、基本的に「静的な」メソッドを配置できる場所を提供します。さらに、コンパニオンオブジェクトまたはコンパニオンモジュールは、プライベートメンバーを含むクラスメンバーへのフルアクセスを持ちます。

コンパニオンオブジェクトは、ファクトリメソッドなどをカプセル化するのに最適です。たとえば、どこでもFooFooFactoryを使用する代わりに、コンパニオンオブジェクトを持つクラスにファクトリの責任を持たせることができます。

75
Saem

コンパニオンオブジェクトは、クラスのすべてのインスタンスに共通の状態とメソッドを保存するのに便利ですただし、静的を使用しないメソッドまたはフィールド。これらは、継承によってオーバーライドできる通常の仮想メソッドを使用します。 Scala本当に静的なものは何もありません。これを使用する方法はたくさんありますが、ここに簡単な例を示します。

abstract class AnimalCounter
{
    var animals = 0

    def name: String

    def count()
    {
        animals += 1
        println("%d %ss created so far".format(animals, name))
    }
}

abstract class Animal
{
    def companion: AnimalCounter
    companion.count()
}

object Dog extends AnimalCounter
{
    val name = "dog"
}

class Dog extends Animal
{
    def companion = Dog
}

object Cat extends AnimalCounter
{
    val name = "cat"
}

class Cat extends Animal
{
    def companion = Cat
}

次の出力が生成されます。

scala> new Dog
1 dogs created so far

scala> new Cat
1 cats created so far

scala> new Dog
2 dogs created so far

scala> new Cat
2 cats created so far
60
Craig P. Motlin

...そして、付随するクラスの静的ファクトリメソッド(DPではない)を格納するのに適した場所です。それらのオーバーロードされたファクトリメソッドにapply(/.../)という名前を付けると、クラスを作成/初期化できます。

  1. 「新規」なし(それほど重要ではない)

  2. パラメーターの異なるセットを使用して(BlochがEffective Javaテレスコープコンストラクターについて)に書いているものと比較してください)

  3. 抽象(付属)クラスの代わりに作成する派生クラスを決定する機能

サンプルコード:

abstract class AbstractClass;
class RealThing(s: String) extends AbstractClass;
class AlternativeThing(i: Int) extends AbstractClass;
object AbstractClass {
  def apply(s: String) = {
    new RealThing(s)
  }
  def apply(i: Int) = {
    new AlternativeThing(i)
  }
}

// somewhere else you can
val vs = AbstractClass("asdf")  // gives you the RealThing wrapped over string
val vi = AbstractClass(123)  // gives you AlternativeThing wrapped over int

見た目が悪くないため、オブジェクト/ベースクラスのAbstractXxxxxを呼び出しません。抽象的なものを作成するようなものです。それらの名前に本当の意味を与えてください。不変、メソッドレス、ケースクラスの使用を検討し、抽象基本クラスを封印します。

30
Szymon Jachim

Saemが his reply で言ったことに加えて、Scalaコンパイラーは、対応するコンパニオンオブジェクトの型の 暗黙的な変換 ソースまたはターゲットのいずれか)ので、変換をインポートする必要はありません。

一般的なシングルトンオブジェクトの理由について Scalaでのプログラミング のコメント:

第1章で述べたように、Scalaは、Javaよりもオブジェクト指向です。Scala代わりに、Scalaにはシングルトンオブジェクトがあります(p。65)。

19
Fabian Steeg

Scalaで機能コードとオブジェクト指向コードの両方を記述するために、コンパニオンオブジェクトは常にbridgeとして表示されます。多くの場合、入力を行い、処理結果を提供する純粋な関数が必要です。これらの関連する関数をコンパニオンオブジェクトに配置すると、自分とコードの上に構築された誰かのために、簡単に検索して使用できます。

さらに、何もせずにシングルトンパターンを記述するための言語提供機能です。これは、JVMの存続期間中に委任者をカプセル化するためにシングルトンが必要な場合に特に役立ちます。たとえば、単純なHTTPクライアントライブラリをScalaで記述すると、基になるJava実装ベースの委任者をカプセル化し、APIのコンシューマーを純粋な世界に住まわせることができます。

3
Gaurav Abbi

最初は、静的メソッドと非静的メソッドのメソッドを明確に分離します。また、シングルトンクラスを作成する簡単な方法も提供します。

また、他のクラスやトレイトからメソッドを継承することもできます。これは、Java静的メソッドでは実行できません。パラメーターとして渡すことができます。

0
vipin

クラスとオブジェクトを同じ名前で同じファイルに定義する場合、それらはコンパニオンクラスとオブジェクトとして知られています。 Scalaとして静的がないJavaキーワード、Scalaの静的クラスをコンパニオンクラスおよびオブジェクトに置き換えることができます。

詳細については、記事をご覧ください scalaプログラミング)のクラスおよびオブジェクトキーワード

0
FOD