Разница между классом и объектом в Котлине

Я новичок в Kotlin и недавно преобразовал простой файл из java в Kotlin. Мне интересно, почему Android-конвертер изменил мой класс java на объект Kotlin.

Джава:

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

Преобразованный Котлин:

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

Почему это не так:

class MyClass {
    ... etc ...
}

Любая помощь будет с благодарностью благодарна.

Ответ 1

Объект Kotlin похож на класс, который не может быть создан, поэтому его нужно вызвать по имени. (статический класс как таковой)

Андроид-конвертор увидел, что ваш класс содержит только статический метод, поэтому он преобразовал его в объект Kotlin.

Подробнее об этом читайте здесь: http://petersommerhoff.com/dev/kotlin/kotlin-for-java-devs/#objects

Ответ 2

Документация Котлина об этом довольно хороша, поэтому не стесняйтесь читать это.

Выбранный ответ на этот вопрос имеет некоторые плохие фразеологии в его объяснении и может легко ввести в заблуждение людей. Например, объект не является "статическим классом per-say", а скорее является a static instance of a class that there is only one of, иначе известный как singleton.

Возможно, лучший способ показать разницу - посмотреть на декомпилированный код Котлина в форме Java.

Вот объект и класс Kotlin:

object ExampleObject {
  fun example() {
  }
}

class ExampleClass {
  fun example() {
  }
}

Чтобы использовать ExampleClass, вам нужно создать его экземпляр: ExampleClass().example(), но с объектом Kotlin создает для него один экземпляр, и вы никогда не называете его конструктором, вместо этого вы просто ExampleObject.example() к нему статический экземпляр, используя имя: ExampleObject.example().

Вот эквивалентный код Java, который Kotlin будет генерировать:

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

Вы бы использовали объект в Котлине следующим образом:

ExampleObject.example()

Что бы скомпилировать до эквивалентного байтового кода Java для:

ExampleObject.INSTANCE.example()

Основной случай использования object в Котлине состоит в том, что Котлин пытается покончить со статическими и примитивными, оставив нам чисто объектно-ориентированный язык. Kotlin по-прежнему использует static и примитивные элементы под капотом, но это препятствует разработчикам использовать эти концепции. Вместо этого теперь Котлин заменяет статические экземпляры объектов singleton. Если раньше вы использовали статическое поле в Java, то в Kotlin вы теперь создадите object и поместите это поле в object.

Поскольку Kotlin на 100% совместим с Java, иногда вам нужно выставлять определенные API или поля таким образом, чтобы лучше читать Java. Для этого вы можете использовать аннотацию @JvmStatic. @JvmStatic поле или функцию в object с @JvmStatic, оно скомпилируется до статических полей, которые Java может использовать проще.

Последнее, что стоит упомянуть, является companion object s. В Java обычно есть классы с некоторым статическим контентом, а также некоторые нестатические/экземпляры содержимого. Котлин позволяет сделать что - то подобное с сопутствующими объектами, которые являются object привязан к class, то есть класс может получить доступ к нему спутник объекта частные функции и свойства:

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

Ответ 3

Объект является одноэлементным. Вам не нужно создавать экземпляр для его использования.

Необходимо использовать экземпляр класса для использования

Точно так же, как в Java вы можете сказать Math.sqrt(2), и вам не нужно создавать экземпляр Math для использования sqrt, в Kotlin вы можете создать объект для хранения этих методов, и они эффективно статичны.

Здесь есть информация:

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

IntelliJ, очевидно, достаточно умен, чтобы обнаружить, что вам нужен объект, поскольку у вас есть только статические java-методы.

Ответ 4

Также вы можете определять функции без объявления объекта. Просто в.kt файле Например:

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

И эта функция была связана с пакетом, где объявлен файл.kt. Подробнее об этом можно узнать здесь https://kotlinlang.org/docs/reference/packages.html