Sự khác biệt giữa một lớp và đối tượng trong Kotlin


98

Tôi mới sử dụng Kotlin và gần đây đã chuyển đổi một tệp đơn giản từ java sang Kotlin. Tôi đang tự hỏi tại sao trình chuyển đổi Android lại thay đổi lớp java của tôi thành đối tượng 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 được chuyển đổi:

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

Tại sao không phải:

class MyClass {
    ... etc ...
}

Mọi sự trợ giúp đều rất được trân trọng, xin cảm ơn.

Câu trả lời:


96

Một đối tượng Kotlin giống như một lớp không thể được khởi tạo nên nó phải được gọi bằng tên. (mỗi lớp tĩnh)

Trình chuyển đổi android thấy rằng lớp của bạn chỉ chứa một phương thức tĩnh, vì vậy nó đã chuyển đổi nó thành đối tượng Kotlin.

Đọc thêm về nó tại đây: http://petersommerhoff.com/dev/kotlin/kotlin-for-java-devs/#objects


164

Tài liệu của Kotlin về vấn đề này khá tốt, vì vậy hãy đọc nó.

Câu trả lời được chọn cho câu hỏi này có một số cụm từ kém trong giải thích của nó và có thể dễ dàng đánh lừa mọi người. Ví dụ, một đối tượng không phải là "một lớp tĩnh mỗi lần", mà đúng hơn nó là a static instance of a class that there is only one of, hay được gọi là một singleton.

Có lẽ cách tốt nhất để thể hiện sự khác biệt là xem mã Kotlin đã được dịch ngược ở dạng Java.

Đối tượng và lớp Kotlin:

object ExampleObject {
  fun example() {
  }
}

class ExampleClass {
  fun example() {
  }
}

Để sử dụng ExampleClass, bạn cần tạo một thể hiện của nó ExampleClass().example():, nhưng với một đối tượng, Kotlin tạo một thể hiện duy nhất của nó cho bạn và bạn không bao giờ gọi nó là hàm tạo, thay vào đó bạn chỉ cần truy cập vào thể hiện tĩnh của nó bằng cách sử dụng tên: ExampleObject.example().

Mã Java tương đương Kotlin sẽ tạo ra:

Kotlin biên dịch sang mã byte Java, nhưng nếu chúng ta biên dịch ngược lại mã Kotlin đã biên dịch ở trên sang mã Java thì đây là những gì chúng ta nhận được:

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

Bạn sẽ sử dụng đối tượng trong Kotlin theo cách sau:

ExampleObject.example()

Điều này sẽ biên dịch xuống mã byte Java tương đương cho:

ExampleObject.INSTANCE.example()

Tại sao Kotlin lại giới thiệu objects?

Trường hợp sử dụng chính của objecttrong Kotlin là bởi vì Kotlin cố gắng loại bỏ tĩnh và nguyên thủy, để lại cho chúng ta một ngôn ngữ hướng đối tượng thuần túy. Kotlin vẫn sử dụng staticvà nguyên thủy bên dưới mui xe, nhưng nó không khuyến khích các nhà phát triển sử dụng những khái niệm đó nữa. Thay vào đó, bây giờ Kotlin thay thế static bằng các trường hợp đối tượng singleton. Nơi mà trước đây bạn sẽ sử dụng trường tĩnh trong Java, trong Kotlin bây giờ bạn sẽ tạo objectvà đặt trường đó vào object.

Khả năng tương tác với Java:

Vì Kotlin có thể tương tác 100% với Java nên đôi khi bạn sẽ muốn hiển thị các API hoặc trường nhất định theo cách đẹp hơn để Java đọc. Để làm điều này, bạn có thể sử dụng @JvmStaticchú thích. Bằng cách chú thích một trường hoặc một hàm trong objectvới @JvmStatic, nó sẽ biên dịch thành các trường tĩnh mà Java có thể sử dụng dễ dàng hơn.

Đối tượng Đồng hành:

Một điều cuối cùng đáng nói là companion objects. Trong Java, bạn thường có các lớp có một số nội dung tĩnh, nhưng cũng có một số nội dung không tĩnh / phiên bản. Kotlin cho phép bạn làm điều gì đó tương tự với các đối tượng đồng hành, được objectgắn với a class, nghĩa là một lớp có thể truy cập các chức năng và thuộc tính riêng của đối tượng đồng hành đó:

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
Lời giải thích hay. Cảm ơn rất nhiều.
Ansari tiếng Đan Mạch

12

Một đối tượng là một singleton. Bạn không cần tạo một thể hiện để sử dụng nó.

Một lớp cần được khởi tạo để sử dụng

Theo cách tương tự như trong Java, bạn có thể nói Math.sqrt (2) và bạn không cần tạo một cá thể Math để sử dụng sqrt, trong Kotlin, bạn có thể tạo một đối tượng để chứa các phương thức này và chúng có hiệu quả tĩnh.

Có một số thông tin ở đây:

https://kotlinlang.org/docs/reference/object-decl Tuyên.html

Rõ ràng IntelliJ đã đủ thông minh để phát hiện bạn cần một đối tượng vì bạn chỉ có các phương thức java tĩnh.


Chờ đã nhưng nếu lớp của tôi Humancó một trường int tĩnh Population, thì trường đó sẽ như thế nào trong Kotlin? companion object { @JvmField val Population; }hay gì đó?
Squirrelkiller

3

Ngoài ra, bạn có thể định nghĩa các hàm mà không cần khai báo đối tượng. Chỉ trong tệp .kt Ví dụ:

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

Và chức năng này liên quan đến gói nơi tệp .kt được khai báo. Bạn có thể đọc thêm về nó tại đây https://kotlinlang.org/docs/reference/packages.html


1

Dựa trên câu trả lời của @ Speirce7:

Đoạn mã sau cho thấy sự khác biệt cơ bản giữa Lớp và Đối tượng khi nói đến 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.
}
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.