Differenza tra una classe e un oggetto in Kotlin


99

Sono nuovo di Kotlin e di recente ho convertito un semplice file da java a Kotlin. Mi chiedo perché il convertitore Android abbia cambiato la mia classe java in un oggetto Kotlin.

Giava:

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;
    }
}

Kotlin convertito:

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
    }
}

Perché non era:

class MyClass {
    ... etc ...
}

Qualsiasi aiuto sarebbe molto apprezzato, grazie.

Risposte:



166

La documentazione di Kotlin su questo è abbastanza buona, quindi sentiti libero di leggerla.

La risposta scelta per questa domanda ha una povera fraseologia nella sua spiegazione e potrebbe facilmente fuorviare le persone. Ad esempio, un oggetto non è "una classe statica di per sé", ma piuttosto lo è a static instance of a class that there is only one of, altrimenti noto come singleton.

Forse il modo migliore per mostrare la differenza è guardare il codice Kotlin decompilato in formato Java.

Oggetto e classe Kotlin:

object ExampleObject {
  fun example() {
  }
}

class ExampleClass {
  fun example() {
  }
}

Per poter utilizzare ExampleClass, è necessario crearne un'istanza ExampleClass().example():, ma con un oggetto, Kotlin ne crea una singola istanza per te e non chiami mai il suo costruttore, invece accedi semplicemente alla sua istanza statica usando il nome: ExampleObject.example().

Il codice Java equivalente che Kotlin genererebbe:

Kotlin compila in codice byte Java, ma se invertiamo la compilazione del codice Kotlin compilato sopra in codice Java, questo è ciò che otteniamo:

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() {
   }
}

Useresti l'oggetto in Kotlin nel modo seguente:

ExampleObject.example()

Che verrebbe compilato fino al codice byte Java equivalente per:

ExampleObject.INSTANCE.example()

Perché Kotlin introduce objects?

Il caso d'uso principale di objectin Kotlin è perché Kotlin cerca di farla finita con statico e primitivo, lasciandoci con un linguaggio puramente orientato agli oggetti. Kotlin usa ancora statice primitive sotto il cofano, ma scoraggia gli sviluppatori a usare ancora quei concetti. Invece, ora Kotlin sostituisce static con istanze di oggetti singleton. Dove in precedenza avresti utilizzato il campo statico in Java, in Kotlin ora creerai un objectcampo e lo inserirai nel file object.

Interoperabilità con Java:

Poiché Kotlin è interoperabile al 100% con Java, a volte potresti voler esporre determinate API o campi in un modo che sia più piacevole da leggere per Java. Per fare ciò, puoi usare l' @JvmStaticannotazione. Annotando un campo o una funzione in un objectcon @JvmStatic, verrà compilato in campi statici che Java può utilizzare più facilmente.

Oggetti companion:

Un'ultima cosa che vale la pena menzionare è companion objects. In Java, in genere si hanno classi con contenuto statico, ma anche contenuto non statico / istanza. Kotlin ti consente di fare qualcosa di simile con gli oggetti associati, che sono objectlegati a class, il che significa che una classe può accedere alle funzioni e proprietà private del suo oggetto compagno:

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)
  }
}

6
Bella spiegazione. Molte grazie.
Ansari danese

12

Un oggetto è un singleton. Non è necessario creare un'istanza per utilizzarlo.

Una classe deve essere istanziata per essere utilizzata

Allo stesso modo in cui in Java si può dire Math.sqrt (2) e non è necessario creare un'istanza Math per utilizzare sqrt, in Kotlin è possibile creare un oggetto per contenere questi metodi, che sono effettivamente statici.

Ci sono alcune informazioni qui:

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

IntelliJ è stato ovviamente abbastanza intelligente da rilevare che hai bisogno di un oggetto poiché hai solo metodi java statici.


Aspetta, ma se la mia classe Humanha un campo int statico Population, come sarebbe in Kotlin? companion object { @JvmField val Population; }o qualcosa?
Squirrelkiller

3

Inoltre è possibile definire funzioni senza dichiarazione di oggetto. Solo nel file .kt Ad esempio:

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

E questa funzione era correlata al pacchetto in cui è dichiarato il file .kt. Puoi leggere di più al riguardo qui https://kotlinlang.org/docs/reference/packages.html


1

Basandosi sulla risposta di @ speirce7:

Il codice seguente mostra la differenza fondamentale tra una classe e un oggetto quando si tratta di Kotlin:

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.
}
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.