Scalaにコンパニオンオブジェクトがある理由は何ですか?


107

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



参照してくださいstackoverflow.com/a/9806136/736957ここでの回答の良いコンパイルしている
laughedelic

回答:


82

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

コンパニオンオブジェクトは、ファクトリメソッドなどのカプセル化に最適です。代わりに、たとえば、持っている、したのFooFooFactoryどこでも、あなたは工場出荷時の責任のコンパニオンオブジェクトテイクを持つクラスを持つことができます。


61

コンパニオンオブジェクトは、クラスのすべてのインスタンスに共通の状態とメソッドを格納するのに役立ちますが、静的メソッドやフィールドは使用しません。これらは、継承によってオーバーライドできる通常の仮想メソッドを使用します。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

1
同様の図はここにもあります:daily-scala.blogspot.sk/2009/09/companion-object.html
xhudik

30

...これは、付随するクラスの静的ファクトリメソッド(その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と呼んではいけません。それらの名前に本当の意味を与えてください。不変、メソッドレス、caseクラスの使用を検討し、抽象基本クラスをシールしてください。


2
RealThingまた、AlternativeThingクラスにはprivate、ユーザーAbstractClassがhasファクトリを使用するように強制するコンストラクターが必要です。class AlternativeThing private(i: Int) extends AbstractClass
metch、2014年

@ [Szymon Jachim] Scala抽象クラスは多重継承をサポートしていません。それで、コンパイラはなぜあなたのケースでそれを許可するのですか?
user2441441

19

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

一般的に、シングルトンオブジェクトの理由についてスカラ座でのプログラミング言います:

第1章で述べたように、ScalaがJavaよりもオブジェクト指向である1つの方法は、Scalaのクラスが静的メンバーを持つことができないことです。代わりに、Scalaにはシングルトンオブジェクト(p。


3

私はコンパニオンオブジェクトを、Scalaで関数型とオブジェクト指向の両方のコードを記述するための橋渡しとして常に見ています。多くの場合、入力を受け取り、処理結果を提供する純粋な関数が必要です。これらの関連する関数をコンパニオンオブジェクトに配置することで、自分自身とコードの上に構築されたいくつかの人にとって、検索と使用が簡単になります。

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


0

クラスとオブジェクトを同じ名前で同じファイルに定義する場合、それらはコンパニオンクラスとオブジェクトと呼ばれます。Scalaには、JAVAキーワードとしてstaticがありません。Scalaでは、静的クラスをコンパニオンクラスとオブジェクトで置き換えることができます。

詳細については、Scalaプログラミングの記事クラスとオブジェクトキーワードを確認してください。


-1

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

また、Java静的メソッドでは実行できない他のクラスや特性からメソッドを継承することもできます。また、パラメーターとして渡すこともできます。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.