【问题标题】:Difference between a class and object in KotlinKotlin 中类和对象的区别
【发布时间】:2017-10-30 13:22:12
【问题描述】:

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

任何帮助将不胜感激。

【问题讨论】:

    标签: java android kotlin


    【解决方案1】:

    Kotlin's documentation 这个不错,欢迎阅读。

    为这个问题选择的答案在解释中措辞不佳,很容易误导人们。例如,一个对象不是“一个静态类本身”,而是a static instance of a class that there is only one of,也称为单例。

    也许显示差异的最佳方法是查看 Java 形式的反编译 Kotlin 代码。

    Kotlin 对象和类:

    object ExampleObject {
      fun example() {
      }
    }
    
    class ExampleClass {
      fun example() {
      }
    }
    

    为了使用ExampleClass,你需要创建它的一个实例:ExampleClass().example(),但是对于一个对象,Kotlin 会为你创建它的一个实例,你永远不会称它为构造函数,相反,您只需使用名称访问它的静态实例:ExampleObject.example()

    Kotlin 将生成的等效 Java 代码:

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

    Kotlin 为什么要引入objects?

    object 在 Kotlin 中的主要用例是因为 Kotlin 试图消除静态和原语,从而为我们留下了纯粹的面向对象语言。 Kotlin 仍然在底层使用static 和原语,但它不鼓励开发人员再使用这些概念。相反,现在 Kotlin 将静态替换为单例对象实例。您以前在 Java 中使用静态字段,现在在 Kotlin 中您将创建一个 object,并将该字段放入 object

    与 Java 的互操作性:

    因为 Kotlin 与 Java 100% 可互操作,所以有时您会希望以一种更便于 Java 阅读的方式公开某些 API 或字段。为此,您可以使用@JvmStatic 注释。通过使用@JvmStatic 注释object 中的字段或函数,它将编译为Java 可以更轻松地使用的静态字段。

    伴随对象:

    最后值得一提的是companion objects。在 Java 中,您的类通常具有一些静态内容,但也有一些非静态/实例内容。 Kotlin 允许您对伴随对象执行类似的操作,这些伴随对象是 objects 绑定到 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)
      }
    }
    

    【讨论】:

    • 很好的解释。非常感谢。
    • 是的,这就是为什么“伴生对象”在类中被称为“对象”的原因。它实际上是一个类中的单例。
    【解决方案2】:

    Kotlin 对象就像一个无法实例化的类,因此必须通过名称调用它。 (本身就是一个静态类)

    android 转换器看到你的类只包含一个静态方法,所以它把它转换成一个 Kotlin 对象。

    在此处了解更多信息:http://petersommerhoff.com/dev/kotlin/kotlin-for-java-devs/#objects

    【讨论】:

      【解决方案3】:

      一个对象是一个单例。您无需创建实例即可使用它。

      一个类需要被实例化才能使用

      就像在 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; } 什么的?
      【解决方案4】:

      不同:对象 || || 伴侣对象 || 数据类

      1.对象

      • 对象声明在第一次访问时被延迟初始化。
      • 对象的行为类似于单例类
      • 整个应用只有一个参考
      • 无需创建实例即可访问成员、方法

      2.类

      • 您可以创建多个参考
      • 需要为访问成员、方法创建实例

      3.companion 对象

      • 在加载相应的类时初始化伴随对象
      • object MyClass{} 中,默认情况下整个变量只有一个引用,但在companion object 中,您可以选择创建静态方法或创建静态变量
      • 您可以创建单例类

      4.数据类

      • 用于保存数据/状态的类
      • Kotlin 的数据类,您无需自己编写/生成所有冗长的样板代码
      • 编译器会自动为所有可变属性生成默认的 getter 和 setter
      • 编译器自动派生标准方法的实现,如equals()hashCode()toString()

      示例

      //---------------1- object ----------------------
      object MyClass1 {
              fun checkData {
                  // ...
              }
      }
      
      MyClass1.checkData()  // call method
      
      
      //----------------2- class ---------------------
      class MyClass2 {
              fun checkData {
                  // ...
              }
      }
      
      var myClass = MyClass2()
      myClass.checkData()  // call method
      
      
      
      //----------------3- companion object ---------------------
      class MyClass3 {
              companion object {
                  fun myStaticMethod() {
                      // ...
                  }
              }
      
             fun myInstanceMethod() {
                  // ...
              }
      }
      MyClass3.myStaticMethod() // call companion object member
      var myClass = MyClass3()
      myClass.myInstanceMethod()  // call simple method using reference
      
      //----------------4- data class ---------------------
      data class MyClass4(val name: String, val rId: Int)
      

      【讨论】:

        【解决方案5】:

        您也可以在没有对象声明的情况下定义函数。就在 .kt 文件中 例如:

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

        并且这个函数与声明 .kt 文件的包有关。 你可以在这里阅读更多关于它的信息https://kotlinlang.org/docs/reference/packages.html

        【讨论】:

          【解决方案6】:

          基于@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.
          }
          

          【讨论】:

            猜你喜欢
            • 2017-10-04
            • 2011-03-27
            • 1970-01-01
            • 1970-01-01
            • 2010-12-17
            • 1970-01-01
            • 2011-03-02
            • 2020-02-06
            • 1970-01-01
            相关资源
            最近更新 更多