Diferencia entre una clase y un objeto en Kotlin


98

Soy nuevo en Kotlin y recientemente he convertido un archivo simple de Java a Kotlin. Me pregunto por qué el convertidor de Android cambió mi clase java a un 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 qué no fue así?

class MyClass {
    ... etc ...
}

Cualquier ayuda sería muy apreciada, gracias.

Respuestas:



164

La documentación de Kotlin sobre esto es bastante buena, así que no dudes en leerla.

La respuesta elegida para esta pregunta tiene una fraseología pobre en su explicación y podría engañar fácilmente a la gente. Por ejemplo, un objeto no es "una clase estática per se", sino que lo es a static instance of a class that there is only one of, también conocido como singleton.

Quizás la mejor manera de mostrar la diferencia es mirar el código Kotlin descompilado en formato Java.

Objeto y clase de Kotlin:

object ExampleObject {
  fun example() {
  }
}

class ExampleClass {
  fun example() {
  }
}

Para usar el ExampleClass, necesitas crear una instancia de él:, ExampleClass().example()pero con un objeto, Kotlin crea una sola instancia de él para ti, y nunca llamas a su constructor, en su lugar, solo accedes a su instancia estática usando el nombre de: ExampleObject.example().

El código Java equivalente que generaría Kotlin:

Kotlin compila en código de bytes de Java, pero si revertimos la compilación del código de Kotlin compilado anteriormente en código de Java, esto es lo que obtenemos:

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

Usaría el objeto en Kotlin de la siguiente manera:

ExampleObject.example()

Que se compilaría en el código de bytes de Java equivalente para:

ExampleObject.INSTANCE.example()

¿Por qué Kotlin presenta objects?

El caso de uso principal de objecten Kotlin es porque Kotlin intenta eliminar los estáticos y los primitivos, dejándonos con un lenguaje puramente orientado a objetos. Kotlin todavía usa staticy primitivos debajo del capó, pero desalienta a los desarrolladores a usar esos conceptos más. En cambio, ahora Kotlin reemplaza instancias de objetos estáticos con singleton. Donde antes usaba un campo estático en Java, en Kotlin ahora creará un objecty pondrá ese campo en el object.

Interoperabilidad con Java:

Debido a que Kotlin es 100% interoperable con Java, a veces querrá exponer ciertas API o campos de una manera que sea más agradable de leer para Java. Para hacer esto, puede usar la @JvmStaticanotación. Al anotar un campo o una función en un objectcon @JvmStatic, se compilará en campos estáticos que Java puede usar más fácilmente.

Objetos complementarios:

Una última cosa que vale la pena mencionar es la companion objects. En Java, normalmente tiene clases que tienen contenido estático, pero también contenido no estático / de instancia. Kotlin le permite hacer algo similar con los objetos complementarios, que están objectvinculados a a class, lo que significa que una clase puede acceder a las funciones y propiedades privadas de su objeto complementario:

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
Buena explicación. Muchas gracias.
Danish Ansari

12

Un objeto es un singleton. No es necesario crear una instancia para usarlo.

Es necesario crear una instancia de una clase para poder usarla

De la misma manera que en Java puede decir Math.sqrt (2) y no necesita crear una instancia de Math para usar sqrt, en Kotlin puede crear un objeto para contener estos métodos, y son efectivamente estáticos.

Hay algo de información aquí:

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

IntelliJ obviamente ha sido lo suficientemente inteligente como para detectar que necesita un objeto, ya que solo tiene métodos estáticos de Java.


Espera, pero si mi clase Humantiene un campo int estático Population, ¿cómo se vería eso en Kotlin? companion object { @JvmField val Population; }¿o algo?
Squirrelkiller

3

También puede definir funciones sin declaración de objeto. Solo en archivo .kt Por ejemplo:

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

Y esta función estaba relacionada con el paquete donde se declara el archivo .kt. Puede leer más sobre esto aquí https://kotlinlang.org/docs/reference/packages.html


1

Basándose en la respuesta de @ speirce7:

El siguiente código muestra la diferencia básica entre una clase y un objeto cuando 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.
}
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.