Die Deklaration von Konstanten und die Verwendung von Companion Objects sind wichtige Konzepte in Kotlin, die die gewohnten static-Mitglieder aus Java abgelöst haben und die damit verbundenen Schwierigkeiten bei der Überbrückung von OOP- und funktionalen Programmierparadigmen beseitigen.
Historie der Frage: In Java werden für Konstanten normalerweise static final-Felder verwendet, während statische Methoden für Hilfs- oder Fabrikfunktionen genutzt werden. In Kotlin wurden anstelle von static object und companion object eingeführt, und für compile-time Konstanten gibt es das Schlüsselwort const.
Problem: Es müssen Werte deklariert werden, die unabhängig von Instanzklassen sind, und Fabrikmethoden sowie statische Zustände organisiert werden, ohne die Integrität der OOP zu verletzen.
Lösung: Companion Objects (Companion Object) werden innerhalb einer Klasse deklariert und ermöglichen es, Mitglieder zu platzieren, die für alle Instanzen gemeinsam sind:
Codebeispiel:
class MyClass { companion object { const val DEFAULT_LIMIT = 10 fun create(): MyClass = MyClass() } } val limit = MyClass.DEFAULT_LIMIT val instance = MyClass.create()
Wesentliche Merkmale:
Kann ein Companion Object mehrere Instanzen in einer Klasse haben?
Nein, in einer Klasse kann es nur ein Companion Object geben. Der Versuch, einen zweiten zu deklarieren, führt zu einem Kompilierungsfehler. Innerhalb des companion objects sind jedoch beliebig viele Methoden/Eigenschaften erlaubt.
Kann man lateinit-Variablen innerhalb des companion objects initialisieren?
Nein, denn Eigenschaften mit const oder Variablen innerhalb des companion objects müssen entweder sofort initialisiert werden oder val/var mit expliziter Initialisierung sein. lateinit ist für Eigenschaften im companion object nicht erlaubt.
Kann ein Companion Object einen eigenen Namen haben und wann ist das erforderlich?
Ja, der Name des Companion Objects wird ausdrücklich festgelegt, wenn man auf ihn über den Namen zugreifen oder beispielsweise Interfaces implementieren möchte. In anderen Fällen ist es optional. Beispiel:
class Foo { companion object Factory { fun create(): Foo = Foo() } } val instance = Foo.Factory.create()
Alle Hilfsfunktionen und globalen Variablen des Programms werden im companion object platziert, verwenden var anstelle von val/const:
Vorteile:
Nachteile:
Es werden nur compile-time Konstanten (const val) und reine Funktionen innerhalb des companion objects verwendet, alles Änderbare ist entweder lokalisiert oder wird über DI übergeben:
Vorteile:
Nachteile: