Kotlin: Unterschied zwischen Objekt und Begleitobjekt in einer Klasse


75

Was ist der Unterschied zwischen einem Objekt und einem Begleitobjekt in einer Klasse in Kotlin?

Beispiel:

class MyClass {

    object Holder {
        //something
    }

    companion object {
        //something
    }
}

Ich habe bereits gelesen, dass ein Begleitobjekt verwendet werden soll, wenn die enthaltenen Parameter / Methoden eng mit seiner Klasse zusammenhängen.

Aber warum gibt es auch die Möglichkeit, ein normales Objekt in der Klasse zu deklarieren? Weil es sich genau wie der Begleiter verhält, aber einen Namen haben muss.

Gibt es vielleicht einen Unterschied im "statischen" Lebenszyklus (ich bin von der Java-Seite)?


3
objectfür Singletons und companion objectfür statische Methoden. Kotlin - Objektdeklarationen bieten eine gute Erklärung für die Verwendung.
ArtiomLK

Antworten:


47

Objekte können Schnittstellen implementieren. Innerhalb einer Klasse hat das Definieren eines einfachen Objekts, das keine Schnittstellen implementiert, in den meisten Fällen keinen Vorteil. Das Definieren mehrerer Objekte, die verschiedene Schnittstellen implementieren (z. B. Comparator), kann jedoch sehr nützlich sein.

In Bezug auf den Lebenszyklus gibt es keinen Unterschied zwischen einem Begleitobjekt und einem in einer Klasse deklarierten benannten Objekt.


Perfekt! Vielen Dank für Ihre Erklärung!
Poweranimal

AFAIK gibt es einen Unterschied in der Initialisierungsreihenfolge
Ilya

Was ist die Differenz? Ich würde vermuten, dass der Begleiter zuerst initialisiert wird, weil er an seine Klasse gebunden ist und danach das Objekt aufgerufen wird.
Poweranimal

30
Das Companion-Objekt wird vom statischen Konstruktor der enthaltenden Klasse initialisiert, und das einfache Objekt wird beim ersten Zugriff auf dieses Objekt träge initialisiert.
Ilya

Du hast geantwortet, was ich will ... "Lebenszyklus". Vielen Dank.
Licat Julius

59

Es gibt zwei verschiedene objectVerwendungsarten: Ausdruck und Deklaration .

Objektausdruck

Ein Objektausdruck kann verwendet werden, wenn eine Klasse geringfügig geändert werden muss, es ist jedoch nicht erforderlich, eine völlig neue Unterklasse dafür zu erstellen. Anonyme innere Klassen sind ein gutes Beispiel dafür.

    button.setOnClickListener(object: View.OnClickListener() {
        override fun onClick(view: View) {
            // click event
        }
    })

Eine Sache, auf die Sie achten müssen, ist, dass anonyme innere Klassen auf Variablen aus dem umschließenden Bereich zugreifen können, und diese Variablen müssen es nicht sein final. Dies bedeutet, dass eine Variable, die in einer anonymen inneren Klasse verwendet wird, die nicht berücksichtigt wird final, den Wert unerwartet ändern kann, bevor auf sie zugegriffen wird.

Objektdeklaration

Eine Objektdeklaration ähnelt einer Variablendeklaration und kann daher nicht auf der rechten Seite einer Zuweisungsanweisung verwendet werden. Objektdeklarationen sind sehr nützlich für die Implementierung des Singleton-Musters.

    object MySingletonObject {
        fun getInstance(): MySingletonObject {
            // return single instance of object
        }
    }

Und die getInstanceMethode kann dann so aufgerufen werden.

    MySingletonObject.getInstance()

Begleitobjekt

Ein Begleitobjekt ist eine bestimmte Art von Objektdeklaration, mit der sich ein Objekt ähnlich wie statische Objekte in anderen Sprachen (z. B. Java) verhalten kann. Durch Hinzufügen companionzur Objektdeklaration kann einem Objekt die "statische" Funktionalität hinzugefügt werden, obwohl das eigentliche statische Konzept in Kotlin nicht vorhanden ist. Hier ist ein Beispiel für eine Klasse mit Instanzmethoden und Begleitmethoden.

 class MyClass {
        companion object MyCompanionObject {
            fun actsAsStatic() {
                // do stuff
            }
        }

       fun instanceMethod() {
            // do stuff
        }
    }

Das Aufrufen der Instanzmethode würde folgendermaßen aussehen.

    var myClass = MyClass()
    myClass.instanceMethod()

Das Aufrufen der Companion-Objektmethode würde folgendermaßen aussehen.

    MyClass.actsAsStatic()

Weitere Informationen finden Sie in den Kotlin-Dokumenten .


2
Danke Mike! Dies sollte die Antwort sein.
Rici

2
Ich hatte das Verfahren innerhalb Begleitobjekt zu verwenden , MyClass.MyCompanionObject.actsAsStatic()oder MyClass.Companion.actsAsStatic()wenn der Begleiter Objekt keinen Namen hat. Ist das eine neue Änderung oder habe ich etwas falsch gemacht? Vielen Dank.
Supriya

7

Ein Objekt oder eine Objektdeklaration wird beim ersten Zugriff träge initialisiert.

Ein Begleitobjekt wird initialisiert, wenn die entsprechende Klasse geladen wird. Es bewirkt die "statische" Essenz, obwohl Kotlin statische Mitglieder nicht von Natur aus unterstützt.


4

Wie Kotlin in Aktion feststellt

Das Objektschlüsselwort wird in Kotlin in mehreren Fällen verwendet, aber alle haben dieselbe Kernidee: Das Schlüsselwort definiert eine Klasse und erstellt gleichzeitig eine Instanz (mit anderen Worten ein Objekt) dieser Klasse.

Wenn es um ein einfaches Objekt und ein Begleitobjekt geht, besteht der einzige wesentliche Unterschied darin, dass auf Eigenschaften und Funktionen eines Begleitobjekts direkt zugegriffen werden kann, indem der Name der enthaltenen Klasse verwendet wird. Das lässt es wie Java Static Member Access erscheinen.

Zum Beispiel, wenn Sie folgende Klasse haben

class Temp{
    object Holder{
        fun foo() = 1
    }

    companion object{
        fun foo() = "Hello World"
    }
}

Anschließend können Sie auf beide Objekte wie folgt zugreifen: From enthält Klasse

foo()   // call to companion object function
Holder.foo() // call to plain object function

und von außerhalb der Klasse

Temp.foo() // call to companion object function
Temp.Holder.foo() // call to plain object function

Unter der Haube erzeugt jede Objektdeklaration einen Singleton. Im Fall eines Begleitobjekts wird das Singleton-Objekt im statischen Initialisierer der enthaltenden Klasse erstellt. Bei einfachen Objekten wird die Singleton-Instanz jedoch träge erstellt, wenn zum ersten Mal auf die Objektklasse zugegriffen wird.

Sie können es selbst sehen, indem Sie die Kotlin-Klasse kompilieren und dann die generierten Klassendateien mit einem Java-Dekompiler dekompilieren.

warum es auch die Möglichkeit gibt, ein normales Objekt in der Klasse zu deklarieren. Betrachten Sie die folgende Klasse, in der das Member-Objekt sehr nützlich ist.

data class Employee(val name: String) {
    object NameComparator : Comparator<Employee> {
         override fun compare(p1: Employee, p2: Employee): Int =
             p1.name.compareTo(p2.name)
    }
}

Jetzt können wir eine Liste der Mitarbeiter als sortieren

list.sortedWith(Employee.NameComparator))

3

Das Companion-Objekt ist vorhanden, da Sie die Funktionen / Eigenschaften von Companion-Objekten wie eine statische Java-Methode / ein statisches Java-Feld aufrufen können. Und warum Sie Holdererlaubt sind, gibt es keinen Grund, warum das Deklarieren eines verschachtelten Objekts illegal ist. Es kann manchmal nützlich sein.


Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.