KotlinのJava静的フィールドの一種の代替として「コンパニオンオブジェクト」を使用する理由


145

「コンパニオンオブジェクト」の意図する意味は何ですか?これまでのstaticところ、必要なときにJavaの代わりに使用しています。

私は混乱しています:

  • なぜ「コンパニオン」と呼ばれているのですか?
  • 複数の静的プロパティを作成するには、companion objectブロック内でグループ化する必要があるということですか?
  • クラスをスコープとするシングルトンインスタンスを即座に作成するために、

companion object {
    val singleton by lazy { ... }
}

これは、一義的な方法のようです。より良い方法は何ですか?

回答:


108
  • 「コンパニオンオブジェクト」の意図する意味は何ですか?なぜ「コンパニオン」と呼ばれているのですか?

    まず、KotlinはstaticメンバーのJavaの概念を使用しません。これは、Kotlinがシングルトン状態に接続されたプロパティと関数を記述するための独自objects概念を持ちstatic、クラスのJava 部分をシングルトンでエレガントに表現できるためです。これは、シングルトンオブジェクトです。クラスの名前で呼び出すことができます。したがって、命名:クラスに付属しているオブジェクトです。

    その名前は以前はclass objectanddefault objectでしたが、名前が変更されcompanion objectてより明確になり、Scalaコンパニオンオブジェクトとも一致します

    命名とは別に、Java staticメンバーよりも強力です。クラスやインターフェースを拡張でき、他のオブジェクトと同じように参照して渡すことができます。

  • 複数の静的プロパティを作成するには、companion objectブロック内でグループ化する必要があるということですか?

    はい、それは慣用的な方法です。または、それらの意味によって非コンパニオンオブジェクトにグループ化することもできます。

    class MyClass {
        object IO {
            fun makeSomethingWithIO() { /* ... */ }
        }
    
        object Factory {
            fun createSomething() { /* ... */ }
        }
    }
  • クラスをスコープとするシングルトンインスタンスを即座に作成するために、私/*...*/はそれを行う一義的な方法のように見えることをよく書いています。より良い方法は何ですか?

    それは、それぞれの特定のケースで何が必要かによって異なります。コードは、クラスへの最初の呼び出しで初期化されるクラスにバインドされた状態を格納するのに適しています。

    クラスに接続する必要がない場合は、オブジェクト宣言を使用します。

    object Foo {
        val something by lazy { ... }
    }

    Java静的初期化子のように、lazy { ... }委譲を削除して、最初のクラスの使用時にプロパティを初期化することもできます。

    シングルトン状態初期化する便利な方法も見つかるかもしれません。


素敵で慣用的な例。
Trein

19

なぜ「コンパニオン」と呼ばれているのですか?

このオブジェクトはインスタンスのコンパニオンです。IIRCここで長い議論がありました:今後の変更クラスオブジェクト再考

複数の静的プロパティを作成するには、コンパニオンオブジェクトブロック内でグループ化する必要があるという意味ですか?

はい。すべての「静的」プロパティ/メソッドは、このコンパニオン内に配置する必要があります。

クラスをスコープとするシングルトンインスタンスを即座に作成するために、

シングルトンインスタンスはすぐには作成されません。singleton初めてアクセスしたときに作成されます。

これは、一義的な方法のようです。より良い方法は何ですか?

むしろobject Singleton { }シングルトンクラスを定義するために行きます。参照:オブジェクト宣言 のインスタンスを作成する必要はなくSingleton、そのように使用するだけですSingleton.doWork()

Kotlinには、コードを整理するための他のものが用意されていることに注意してください。単純な静的関数に代わるものがあります。たとえば、代わりにトップレベル関数を使用できます。


7

なぜ「コンパニオン」と呼ばれているのですか?

クラス内のオブジェクト宣言は、コンパニオンキーワードでマークできます。

class MyClass {
    companion object Factory {
        fun create(): MyClass = MyClass()
    }
}

コンパニオンオブジェクトのメンバーは、クラス名を修飾子として使用するだけで呼び出すことができます。

val instance = MyClass.create()

「コンパニオン」なしで「オブジェクト」のみを使用する場合は、次のようにする必要があります。

val instance = MyClass.Factory.create()

私の理解では、「コンパニオン」とは、このオブジェクトが外部クラスとコンパニオンであることを意味します。


「コンパニオン」のない「オブジェクト」は、次のように呼び出されます(MyClass()。create())。シングルトンのようですが、シングルトンオブジェクトにアクセスするには、最初に「外部」クラスを初期化する必要があります。
LiTTle 2018年

0

コンパニオンはJavaのような「静的ブロック」と同じであると言えますが、Kotlinの場合、コンパニオンがフレームに入るのと同じように静的ブロックの概念はありません。

コンパニオンブロックを定義する方法:

class Example {
      companion object {
        fun display(){
        //place your code
     }
  }
}

コンパニオンブロックの呼び出しメソッド、クラス名で直接

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