Diferença entre uma classe e um objeto em Kotlin

98

Sou novo no Kotlin e recentemente converti um arquivo simples de java para Kotlin. Estou me perguntando por que o conversor do Android mudou minha classe java para um objeto Kotlin.

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

Kotlin convertido:

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

Por que não foi:

class MyClass {
    ... etc ...
}

Qualquer ajuda seria muito apreciada, obrigado.

Crocante 234
fonte

Respostas:

96

Um objeto Kotlin é como uma classe que não pode ser instanciada, portanto, deve ser chamada pelo nome. (uma classe estática per se)

O conversor do Android viu que sua classe continha apenas um método estático, então o converteu em um objeto Kotlin.

Leia mais sobre isso aqui: http://petersommerhoff.com/dev/kotlin/kotlin-for-java-devs/#objects

Título
fonte
164

A documentação de Kotlin sobre isso é muito boa, fique à vontade para lê-la.

A resposta escolhida para esta pergunta tem alguma fraseologia pobre em sua explicação e pode facilmente enganar as pessoas. Por exemplo, um objeto não é "uma classe estática per se", mas sim a static instance of a class that there is only one of, também conhecido como singleton.

Talvez a melhor maneira de mostrar a diferença seja examinar o código Kotlin descompilado no formato Java.

Objeto e classe Kotlin:

object ExampleObject {
  fun example() {
  }
}

class ExampleClass {
  fun example() {
  }
}

Para usar o ExampleClass, você precisa criar uma instância dele ExampleClass().example():, mas com um objeto, Kotlin cria uma única instância dele para você, e você nunca chama seu construtor, em vez disso, você apenas acessa sua instância estática usando o nome: ExampleObject.example().

Código Java equivalente que o Kotlin geraria:

O Kotlin compila para o código de bytes Java, mas se compilarmos de forma reversa o código Kotlin compilado acima para o código Java, obteremos:

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

Você usaria o objeto em Kotlin da seguinte maneira:

ExampleObject.example()

Que compilaria para o código de byte Java equivalente para:

ExampleObject.INSTANCE.example()

Por que Kotlin apresenta objects?

O principal caso de uso de objectem Kotlin é porque Kotlin tenta eliminar estáticos e primitivos, deixando-nos com uma linguagem puramente orientada a objetos. O Kotlin ainda usa statice primitivos por baixo do capô, mas desencoraja os desenvolvedores a usar mais esses conceitos. Em vez disso, agora Kotlin substitui instâncias de objetos estáticos por singleton. Onde você usava anteriormente o campo estático em Java, no Kotlin você criará um objecte colocará esse campo no object.

Interoperabilidade com Java:

Como o Kotlin é 100% interoperável com o Java, às vezes você desejará expor certas APIs ou campos de uma maneira que seja mais agradável para o Java ler. Para fazer isso, você pode usar a @JvmStaticanotação. Ao anotar um campo ou uma função em um objectcom @JvmStatic, ele compilará para campos estáticos que o Java pode usar mais facilmente.

Objetos complementares:

Uma última coisa que vale a pena mencionar é companion objects. Em Java, você normalmente tem classes com algum conteúdo estático, mas também algum conteúdo não estático / instância. O Kotlin permite que você faça algo semelhante com objetos complementares, que são objectvinculados a um class, o que significa que uma classe pode acessar as funções e propriedades privadas do objeto associado:

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
fonte
6
Bela explicação. Muito obrigado.
dinamarquês Ansari
12

Um objeto é um singleton. Você não precisa criar uma instância para usá-lo.

Uma classe precisa ser instanciada para ser usada

Da mesma forma que em Java você pode dizer Math.sqrt (2) e não precisa criar uma instância do Math para usar sqrt, em Kotlin você pode criar um objeto para conter esses métodos, e eles são efetivamente estáticos.

Há algumas informações aqui:

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

O IntelliJ obviamente foi inteligente o suficiente para detectar que você precisa de um objeto, já que você só tem métodos java estáticos.

Bruce Lowe
fonte
Espere, mas se minha classe Humantiver um campo int estático Population, como isso seria no Kotlin? companion object { @JvmField val Population; }ou alguma coisa?
Squirrelkiller de
3

Além disso, você pode definir funções sem declaração de objeto. Apenas no arquivo .kt Por exemplo:

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

E esta função estava relacionada ao pacote onde o arquivo .kt é declarado. Você pode ler mais sobre isso aqui https://kotlinlang.org/docs/reference/packages.html

Silvestr
fonte
1

Com base na resposta de @ speirce7:

O código a seguir mostra a diferença básica entre uma classe e um objeto quando se trata de 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
fonte