Różnica między klasą a obiektem w Kotlinie

101

Jestem nowy w Kotlin i niedawno przekonwertowałem prosty plik z javy na Kotlin. Zastanawiam się, dlaczego konwerter Androida zmienił moją klasę Java na obiekt Kotlin.

Jawa:

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

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

Dlaczego tak się nie stało:

class MyClass {
    ... etc ...
}

Każda pomoc byłaby bardzo mile widziana, dzięki.

Chrupiące 234
źródło

Odpowiedzi:

98

Obiekt Kotlin jest podobny do klasy, której nie można utworzyć instancji, dlatego należy go wywołać po nazwie. (klasa statyczna jako taka)

Konwerter systemu Android zobaczył, że Twoja klasa zawiera tylko metodę statyczną, więc przekonwertował ją na obiekt Kotlin.

Przeczytaj więcej na ten temat tutaj: http://petersommerhoff.com/dev/kotlin/kotlin-for-java-devs/#objects

Nagłówek
źródło
168

Dokumentacja Kotlina na ten temat jest całkiem dobra, więc nie krępuj się ją przeczytać.

Wybrana odpowiedź na to pytanie ma słabą frazeologię w wyjaśnieniu i może łatwo wprowadzać ludzi w błąd. Na przykład obiekt nie jest „klasą statyczną per se”, ale raczej jest a static instance of a class that there is only one of, inaczej nazywany singletonem.

Być może najlepszym sposobem pokazania różnicy jest przyjrzenie się zdekompilowanemu kodowi Kotlin w formie Java.

Obiekt i klasa Kotlin:

object ExampleObject {
  fun example() {
  }
}

class ExampleClass {
  fun example() {
  }
}

Aby użyć tego ExampleClass, musisz utworzyć jego instancję: ExampleClass().example()ale z obiektem Kotlin tworzy dla ciebie pojedynczą instancję i nigdy nie wywołujesz jego konstruktora, zamiast tego po prostu uzyskujesz dostęp do jego statycznej instancji za pomocą nazwa: ExampleObject.example().

Równoważny kod Java Kotlin wygenerowałby:

Kotlin kompiluje do kodu bajtowego Javy, ale jeśli skompilujemy powyżej skompilowany kod Kotlin do kodu Java, otrzymamy:

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

Używałbyś obiektu w Kotlinie w następujący sposób:

ExampleObject.example()

Który skompilowałby się do równoważnego kodu bajtowego Java dla:

ExampleObject.INSTANCE.example()

Dlaczego Kotlin wprowadza objects?

Głównym przypadkiem użycia objectw Kotlinie jest to, że Kotlin próbuje pozbyć się statyczności i prymitywów, pozostawiając nam język czysto obiektowy. Kotlin nadal używa statici prymitywów pod maską, ale zniechęca programistów do dalszego korzystania z tych koncepcji. Zamiast tego Kotlin zastępuje teraz statyczne instancjami pojedynczych obiektów. Tam, gdzie wcześniej używałeś pola statycznego w Javie, w Kotlinie utworzysz teraz objecti umieścisz to pole w object.

Współdziałanie z Javą:

Ponieważ Kotlin jest w 100% interoperacyjny z Javą, czasami będziesz chciał udostępnić pewne interfejsy API lub pola w sposób, który jest przyjemniejszy do czytania dla Javy. Aby to zrobić, możesz użyć @JvmStaticadnotacji. Dodając adnotacje do pola lub funkcji w objectwith @JvmStatic, skompiluje się do pól statycznych, z których Java może łatwiej korzystać.

Obiekty towarzyszące:

Ostatnią rzeczą, o której warto wspomnieć, jest companion objects. W Javie zazwyczaj masz klasy, które mają pewną zawartość statyczną, ale także zawartość niestatyczną / instancji. Kotlin pozwala zrobić coś podobnego z obiektami towarzyszącymi, które są objectpowiązane z a class, co oznacza, że ​​klasa może uzyskać dostęp do prywatnych funkcji i właściwości swojego obiektu towarzyszącego:

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
źródło
6
Niezłe wyjaśnienie. Wielkie dzięki.
Duński Ansari
12

Obiekt jest singletonem. Nie musisz tworzyć instancji, aby z niej korzystać.

Aby można było użyć klasy, należy utworzyć instancję

W ten sam sposób, w jaki w Javie możesz powiedzieć Math.sqrt (2) i nie musisz tworzyć instancji Math, aby używać sqrt, w Kotlin możesz utworzyć obiekt do przechowywania tych metod i są one faktycznie statyczne.

Tutaj jest trochę informacji:

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

IntelliJ był oczywiście wystarczająco inteligentny, aby wykryć, że potrzebujesz obiektu, ponieważ masz tylko statyczne metody Java.

Bruce Lowe
źródło
Czekaj, ale jeśli moja klasa Humanma statyczne pole int Population, jak by to wyglądało w Kotlinie? companion object { @JvmField val Population; }lub coś?
Squirrelkiller
3

Możesz także zdefiniować funkcje bez deklaracji obiektu. Tylko w pliku .kt Na przykład:

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

Ta funkcja była związana z pakietem, w którym jest zadeklarowany plik .kt. Możesz przeczytać więcej na ten temat tutaj https://kotlinlang.org/docs/reference/packages.html

Silvestr
źródło
1

Opierając się na odpowiedzi @ speirce7:

Poniższy kod przedstawia podstawową różnicę między klasą a obiektem, jeśli chodzi o 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.
}
Raj
źródło