Різниця між класом і об'єктом у Котліні


98

Я новачок у Kotlin і нещодавно перетворив простий файл з Java у Kotlin. Мені цікаво, чому конвертер Android змінив мій клас Java на об’єкт 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;
    }
}

Перетворений Котлін:

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

Будь-яка допомога буде вдячна спасибі.

Відповіді:


96

Об'єкт Kotlin схожий на клас, який неможливо створити, тому його потрібно викликати за іменем. (статичний клас як такий)

Конвертер android побачив, що ваш клас містить лише статичний метод, тому він перетворив його на об’єкт Kotlin.

Детальніше про це читайте тут: http://petersommerhoff.com/dev/kotlin/kotlin-for-java-devs/#objects


165

Документація Котліна щодо цього досить гарна, тому сміливо читайте це.

Обрана відповідь на це запитання пояснює деякі бідні фразеологізми і може легко ввести людей в оману. Наприклад, об'єкт не є "статичним класом сам по собі", а, скоріше, є 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()але з об'єктом Котлін створює для вас один його екземпляр, і ви ніколи не називаєте його конструктором, натомість ви просто отримуєте доступ до його статичного екземпляра за допомогою назва: 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() {
   }
}

Ви можете використовувати об'єкт у Kotlin наступним чином:

ExampleObject.example()

Який компілюється до еквівалентного байт-коду Java для:

ExampleObject.INSTANCE.example()

Чому Котлін вводить objects?

Основним випадком використання objectв Kotlin є те, що Kotlin намагається покінчити зі статичними та примітивними елементами , залишаючи нам суто об’єктно-орієнтовану мову. Котлін все ще використовує staticі примітиви під капотом, але це не рекомендує розробникам більше використовувати ці концепції. Натомість, зараз Котлін замінює статичні екземпляри одномісних об’єктів. Там, де ви раніше використовували статичне поле в Java, у Kotlin тепер ви створите поле objectі помістите це поле в object.

Взаємодія з Java:

Оскільки Kotlin на 100% сумісний з Java, іноді вам захочеться розкрити певні API або поля таким чином, щоб Java була приємнішою для читання. Для цього можна скористатися @JvmStaticанотацією. Анотуючи поле або функцію в objectз @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)
  }
}

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.
}
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.