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

101

Я новичок в 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 ...
}

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

Хрустящий234
источник

Ответы:

98

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

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

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

Заголовок
источник
168

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

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

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

Объект и класс Kotlin:

object ExampleObject {
  fun example() {
  }
}

class ExampleClass {
  fun example() {
  }
}

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

Эквивалентный код Java Kotlin сгенерирует:

Kotlin компилируется в байт-код Java, но если мы обратным образом скомпилируем скомпилированный выше код Kotlin в код Java, вот что мы получим:

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

Почему Котлин вводит objects?

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

Совместимость с Java:

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

Сопутствующие объекты:

И последнее, о чем стоит упомянуть, - это companion objects. В Java у вас обычно есть классы, которые имеют некоторый статический контент, но также и некоторый нестатический / экземплярный контент. Kotlin позволяет вам делать что-то подобное с сопутствующими объектами, которые objectпривязаны к a 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)
  }
}
Spierce7
источник
6
Хорошее объяснение. Большое спасибо.
Датский Ансари
12

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

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

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

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

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

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

Брюс Лоу
источник
Подождите, но если у моего класса Humanесть статическое поле int Population, как это будет выглядеть в Kotlin? companion object { @JvmField val Population; }или что-то?
Squirrelkiller
3

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

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

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

Сильвестр
источник
1

Основываясь на ответе @ speirce7:

Следующий код показывает основное различие между классом и объектом, когда дело доходит до 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.
}
Радж
источник