Kotlinは、objectキーワードを通じてシングルトンの古典的な概念を拡張します。これにより、次のパターンが実装されます:
object Logger { ... })。シングルトンオブジェクトの例:
object DatabaseManager { fun connect() { /*...*/ } } DatabaseManager.connect()
オブジェクト式:
val listener = object : MouseAdapter() { override fun mouseClicked(e: MouseEvent) { /*...*/ } }
コンパニオンオブジェクト:
class User { companion object Factory { fun create(name: String) = User() } } val user = User.create("Ivan")
ニュアンス:
コンパニオンオブジェクトとオブジェクト宣言の違いは何ですか? すべてのメンバーは静的としてアクセス可能ですか?
回答:
object declaration — グローバルシングルトン、クラス、インターフェイス、または外部レベルのメンバー。companion object — クラス内の特別なタイプのオブジェクト宣言で、そのメンバーはクラス名を通じて静的であるかのように呼び出すことができます。ただしJavaとは異なり、実際にはシングルトンオブジェクトのフィールドです。違いの例:
class A { companion object { fun foo() {} } object NestedObj { fun bar() {} } } A.foo() // OK A.NestedObj.bar() // OKだが、静的メソッドではない
物語
開発者はオブジェクト宣言内にミュータブルな状態を定義し、同期なしで異なるスレッドからそれを使用し始めました。シングルトンオブジェクトがアプリケーション全体で共有され、レースコンディションの原因となることを考慮していませんでした。
物語
クラス内でコンパニオンオブジェクトの代わりにオブジェクトを宣言した場合、静的メソッドの使用が必要でしたが、インスタンスを介して呼び出す必要があり、可読性が低下し、Javaからの移行中にエラーを引き起こしました。
物語
UIコードでプログラマーは毎回イベントハンドラのためにオブジェクト式で新しいオブジェクトを作成していました。彼はそこにシングルトンがあり、状態が保持されると思い込んでいました。その結果、ライフサイクルの誤った扱いによるメモリリークが発生しました。