Kotlin:伴侣对象和顶级对象之间的差异

Mar*_*nyi 24 kotlin

在Kotlin中创建常量的一般模式似乎是使用伴随对象.但是,我也可以在文件级别定义一个常量.为什么不那么受欢迎?我错过了什么吗?

使用伴侣对象:

class Example {
    companion object {
        const val CONSTANT = "something"
}
Run Code Online (Sandbox Code Playgroud)

在顶层:

const val CONSTANT = "something"

class Example {
}
Run Code Online (Sandbox Code Playgroud)

Mar*_*nik 32

在Java中,您被迫将所有静态字段和方法声明放在一个类中,并且通常您甚至必须为此目的创建一个类.来到Kotlin,许多用户出于习惯而寻找相同的设施,最终过度使用伴侣对象.

Kotlin完全解耦了文件和类的概念.您可以声明任意数量的公共类是同一个文件.您还可以声明私有顶级函数和变量,它们只能被同一文件中的类访问.这是组织密切相关的代码和数据的好方法.

与顶级声明相比,伴随对象的语法非常笨拙.只有当您特别想要将某些public static代码或数据与类关联并希望您的用户使用类的名称限定对它的访问权限时,才应使用它们.这种用例非常罕见,在大多数情况下,顶级声明更自然.

每当你想要将某些private static代码/数据耦合到一个类时,你就会更好地使用私有顶级声明.

最后,有时生成的字节码的关注很重要.如果由于某种原因,您必须使用Kotlin代码生成一个Java类,使得该类具有static成员,则必须求助于伴随对象和特殊注释.


jrt*_*ell 15

使用差异

在伴随对象中定义字段会限制其可用范围,而不会仅导入该类,这有助于防止数据在意外位置使用.

在文件中定义使该字段可用于与该字段相同的包中的任何代码.

字节码的差异

const val CONSTANT = "something"

class Example {
}
Run Code Online (Sandbox Code Playgroud)

创建以下内容:

Example.java

public final class Example {}
Run Code Online (Sandbox Code Playgroud)

XKt.java

import kotlin.Metadata;
import org.jetbrains.annotations.NotNull;


public final class XKt {
   public static final String CONSTANT = "something";
}
Run Code Online (Sandbox Code Playgroud)

鉴于:

class Example {
    companion object {
        const val CONSTANT = "something"
    }
}
Run Code Online (Sandbox Code Playgroud)

创建以下内容:

public final class Example {
    public static final String CONSTANT = "something";
    public static final Example.Companion Companion = new Example.Companion((DefaultConstructorMarker) null);

    public static final class Companion {
        private Companion() {}

        public Companion(DefaultConstructorMarker $constructor_marker) {
            this();
        }
    }
}
Run Code Online (Sandbox Code Playgroud)


s1m*_*nw1 5

我认为这基本上取决于您是否希望该常量成为类的一部分。如果将其放在一个companion对象中,将按以下方式对其进行访问:

Example.CONSTANT
Run Code Online (Sandbox Code Playgroud)

如果选择在文件级别上放置一个常量,它将从其他文件中导入并可以简单地CONSTANT正常访问。

将常量放在类中以及将它们放在顶层是有原因的。

请注意,const关键字只能应用于类型String或基本类型(Int等)(参考)的变量。不过,在大多数情况下,无需应用关键字。如下所示定义常量值也可以:

val constantFIS = FileInputStream("path")
Run Code Online (Sandbox Code Playgroud)