Unterschied zwischen einer Klasse und einem Objekt in Kotlin

98

Ich bin neu in Kotlin und habe kürzlich eine einfache Datei von Java nach Kotlin konvertiert. Ich frage mich, warum der Android-Konverter meine Java-Klasse in ein Kotlin-Objekt geändert hat.

Java:

public class MyClass {
    static public int GenerateChecksumCrc16(byte bytes[]) {

        int crc = 0xFFFF;
        int temp;
        int crc_byte;

        for (byte aByte : bytes) {

            crc_byte = aByte;

            for (int bit_index = 0; bit_index < 8; bit_index++) {

                temp = ((crc >> 15)) ^ ((crc_byte >> 7));

                crc <<= 1;
                crc &= 0xFFFF;

                if (temp > 0) {
                    crc ^= 0x1021;
                    crc &= 0xFFFF;
                }

                crc_byte <<= 1;
                crc_byte &= 0xFF;

            }
        }

        return crc;
    }
}

Konvertierter Kotlin:

object MyClass {
    fun GenerateChecksumCrc16(bytes: ByteArray): Int {

        var crc = 0xFFFF
        var temp: Int
        var crc_byte: Int

        for (aByte in bytes) {

            crc_byte = aByte.toInt()

            for (bit_index in 0..7) {

                temp = crc shr 15 xor (crc_byte shr 7)

                crc = crc shl 1
                crc = crc and 0xFFFF

                if (temp > 0) {
                    crc = crc xor 0x1021
                    crc = crc and 0xFFFF
                }

                crc_byte = crc_byte shl 1
                crc_byte = crc_byte and 0xFF

            }
        }

        return crc
    }
}

Warum war es nicht:

class MyClass {
    ... etc ...
}

Jede Hilfe wäre sehr dankbar, danke.

Crunchy234
quelle

Antworten:

96

Ein Kotlin-Objekt ist wie eine Klasse, die nicht instanziiert werden kann, daher muss es beim Namen aufgerufen werden. (eine statische Klasse an sich)

Der Android-Konverter hat festgestellt, dass Ihre Klasse nur eine statische Methode enthält, und hat sie daher in ein Kotlin-Objekt konvertiert.

Lesen Sie hier mehr darüber: http://petersommerhoff.com/dev/kotlin/kotlin-for-java-devs/#objects

Überschrift
quelle
163

Kotlins Dokumentation dazu ist ziemlich gut, also lesen Sie das bitte.

Die gewählte Antwort auf diese Frage hat eine schlechte Ausdrucksweise in ihrer Erklärung und könnte leicht Menschen irreführen. Zum Beispiel ist ein Objekt nicht "eine statische Klasse an sich", sondern es ist a static instance of a class that there is only one ofauch als Singleton bekannt.

Der beste Weg, um den Unterschied zu zeigen, besteht darin, den dekompilierten Kotlin-Code in Java-Form zu betrachten.

Kotlin Objekt und Klasse:

object ExampleObject {
  fun example() {
  }
}

class ExampleClass {
  fun example() {
  }
}

Um das zu verwenden ExampleClass, müssen Sie eine Instanz davon erstellen: ExampleClass().example()Mit einem Objekt erstellt Kotlin jedoch eine einzelne Instanz davon für Sie, und Sie rufen niemals den Konstruktor auf, sondern greifen einfach mit auf die statische Instanz zu der Name : ExampleObject.example().

Äquivalenter Java-Code, den Kotlin generieren würde:

Kotlin kompiliert zu Java-Bytecode, aber wenn wir den oben kompilierten Kotlin-Code rückwärts zu Java-Code kompilieren, erhalten wir Folgendes:

public final class ExampleObject {
   public static final ExampleObject INSTANCE = new ExampleObject();

   private ExampleObject() { }

   public final void example() {
   }
}

public final class ExampleClass {
   public final void example() {
   }
}

Sie würden das Objekt in Kotlin folgendermaßen verwenden:

ExampleObject.example()

Welches würde bis zum entsprechenden Java-Bytecode kompilieren für:

ExampleObject.INSTANCE.example()

Warum führt Kotlin objects ein?

Der Hauptanwendungsfall objectin Kotlin ist, dass Kotlin versucht, statische und primitive Elemente zu beseitigen, wodurch wir eine rein objektorientierte Sprache erhalten. Kotlin verwendet staticund primitiv immer noch unter der Haube, aber es entmutigt Entwickler, diese Konzepte nicht mehr zu verwenden. Stattdessen ersetzt Kotlin jetzt statische durch Singleton-Objektinstanzen. Wo Sie zuvor in Java ein statisches Feld verwendet haben, erstellen Sie in Kotlin jetzt ein objectund fügen dieses Feld in das Feld ein object.

Interoperabilität mit Java:

Da Kotlin zu 100% mit Java interoperabel ist, möchten Sie manchmal bestimmte APIs oder Felder auf eine Weise verfügbar machen, die für Java besser lesbar ist. Dazu können Sie die @JvmStaticAnnotation verwenden. Durch Annotieren eines Felds oder einer Funktion in einem objectwith @JvmStaticwerden statische Felder kompiliert, die Java einfacher verwenden kann.

Begleitobjekte:

Eine letzte erwähnenswerte Sache ist companion objects. In Java gibt es normalerweise Klassen mit statischem Inhalt, aber auch nicht statischem Inhalt / Instanzinhalt. Mit Kotlin können Sie ähnliche Aktionen mit Begleitobjekten ausführen, die objectan a gebunden sind. Dies classbedeutet, dass eine Klasse auf die privaten Funktionen und Eigenschaften ihres Begleitobjekts zugreifen kann:

class ExampleClass {
  companion object {
    // Things that would be static in Java would go here in Kotlin
    private const val str = "asdf"
  }

  fun example() {
    // I can access private variables in my companion object
    println(str)
  }
}
spierce7
quelle
6
Schöne Erklärung. Vielen Dank.
Dänische Ansari
12

Ein Objekt ist ein Singleton. Sie müssen keine Instanz erstellen, um sie zu verwenden.

Eine Klasse muss instanziiert werden, um verwendet zu werden

Genauso wie Sie in Java Math.sqrt (2) sagen und keine Math-Instanz erstellen müssen, um sqrt zu verwenden, können Sie in Kotlin ein Objekt erstellen, das diese Methoden enthält, und sie sind effektiv statisch.

Hier gibt es einige Infos:

https://kotlinlang.org/docs/reference/object-declarations.html

IntelliJ war offensichtlich intelligent genug, um zu erkennen, dass Sie ein Objekt benötigen, da Sie nur statische Java-Methoden haben.

Bruce Lowe
quelle
Warten Sie, aber wenn meine Klasse Humanein statisches int-Feld hat Population, wie würde das in Kotlin aussehen? companion object { @JvmField val Population; }oder so?
Eichhörnchenkiller
3

Sie können auch Funktionen ohne Objektdeklaration definieren. Nur in der .kt-Datei Zum Beispiel:

fun GenerateChecksumCrc16(bytes: ByteArray): Int {
    ...
}

Und diese Funktion bezog sich auf ein Paket, in dem die .kt-Datei deklariert ist. Weitere Informationen finden Sie hier https://kotlinlang.org/docs/reference/packages.html

Silvestr
quelle
1

Aufbauend auf der Antwort von @ speirce7:

Der folgende Code zeigt den grundlegenden Unterschied zwischen einer Klasse und einem Objekt, wenn es um Kotlin geht:

class ExampleClass(){
    fun example(){
            println("I am in the class.")
    }
}

object ExampleObject{
    fun example(){
            println("I am in the object.")
    }
}

fun main(args: Array<String>){
    val exampleClass = ExampleClass() // A class needs to be instantiated.
    exampleClass.example()            // Running the instance of the object.
    ExampleObject.example()           // An object can be thought of as a Singleton and doesn't need any instantiation.
}
Raj
quelle