ความแตกต่างระหว่างคลาสและอ็อบเจ็กต์ใน Kotlin


109

ฉันเพิ่งเริ่มใช้ 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;
    }
}

Kotlin แปลงแล้ว:

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

ความช่วยเหลือใด ๆ จะได้รับการชื่นชมอย่างมากขอบคุณ

คำตอบ:


105

ออบเจ็กต์ Kotlin เป็นเหมือนคลาสที่ไม่สามารถสร้างอินสแตนซ์ได้ดังนั้นจึงต้องเรียกชื่อด้วยชื่อ (คลาสคงที่ต่อ se)

ตัวแปลง android เห็นว่าคลาสของคุณมี แต่วิธีคงที่ดังนั้นมันจึงแปลงเป็นวัตถุ Kotlin

อ่านเพิ่มเติมได้ที่นี่: http://petersommerhoff.com/dev/kotlin/kotlin-for-java-devs/#objects


176

เอกสารของ 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 byte แต่ถ้าเราย้อนกลับคอมไพล์โค้ด 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 byte ที่เทียบเท่าสำหรับ:

ExampleObject.INSTANCE.example()

ทำไม Kotlin ถึงแนะนำobjects?

กรณีการใช้งานหลักของobjectใน Kotlin เป็นเพราะ Kotlin พยายามที่จะหลีกเลี่ยงการใช้งานแบบคงที่และแบบดั้งเดิมทำให้เรามีภาษาที่เน้นวัตถุอย่างหมดจด Kotlin ยังคงใช้staticและดั้งเดิมภายใต้ประทุน แต่ไม่สนับสนุนให้ผู้พัฒนาใช้แนวคิดเหล่านั้นอีกต่อไป ตอนนี้ Kotlin แทนที่สแตติกด้วยอินสแตนซ์อ็อบเจ็กต์ซิงเกิลตัน ก่อนหน้านี้คุณจะใช้ฟิลด์สแตติกใน Java ใน Kotlin ตอนนี้คุณจะสร้างobjectและใส่ฟิลด์นั้นในไฟล์object.

ความสามารถในการทำงานร่วมกันกับ Java:

เนื่องจาก Kotlin สามารถทำงานร่วมกับ Java ได้ 100% บางครั้งคุณอาจต้องการเปิดเผย 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
คำอธิบายที่ดี ขอบคุณมาก.
Ansari ชาวเดนมาร์ก

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

4

นอกจากนี้คุณสามารถกำหนดฟังก์ชันโดยไม่ต้องประกาศวัตถุ เพียงในไฟล์. kt ตัวอย่างเช่น:

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

และฟังก์ชันนี้เกี่ยวข้องกับแพ็กเกจที่มีการประกาศไฟล์. kt คุณสามารถอ่านเพิ่มเติมได้ที่นี่https://kotlinlang.org/docs/reference/packages.html


1

สร้างจากคำตอบของ @ speirce7:

รหัสต่อไปนี้แสดงความแตกต่างพื้นฐานระหว่าง Class และ Object เมื่อพูดถึง 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.
}
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.