24

伴随对象的文档具有以下示例

class MyClass {
    companion object Factory {
        fun create(): MyClass = MyClass()
    }
}

Factory是伴随对象的名称。然后它继续说:

伴生对象的名称可以省略,在这种情况下Companion将使用名称:

但是,我没有看到使用伴随对象名称的示例。

由于每个类只能有一个伴生对象(否则会Only one companion object is allowed per class出错),所以这个名字对我来说就像是一些非常无用的语法糖。

伴生对象的名称实际上可以用来做什么?为什么要费心为它使用任何名称?

4

4 回答 4

14

您可以使用同伴的名称,例如:

MyClass.create()           // not via companion name
MyClass.Companion.create() // via default companion name
MyClass.Factory.create()   // via companion name

这个名字对 Kotlin 来说可能不是那么重要,因为你可以在不知道有伴生对象的情况下访问该方法(上面的第一行)。如果您想让对此类功能的访问更加明确,它更像是一种个人风格。

但是对于java 互操作,它会有所不同,因为您必须通过伴随名称访问该函数:

    MyClass.Factory.create();   // with named companion
    MyClass.Companion.create(); // with unnamed comanion
于 2017-08-24T05:28:26.613 回答
4

好吧,Kotlin 中的伴生对象不仅仅是语法糖。它们实际上是一种类型。他们能够做更多的事情,而不需要仅仅被视为静态的替代品。

您实际上可以扩展类或实现接口。请参阅下面的示例。

open class Super {
    open fun sayHello() {
        println("Hello")
    }
}

class Some {
    companion object Child : Super() {
        override fun sayHello() {
            super.sayHello()
            println("Hello from companion object")
        }
    }
}

fun main() {
    Some.Child.sayHello()
}
于 2020-03-25T21:05:50.750 回答
2

如果您不使用显式名称,则同伴名称为Companion,因此可以省略,就像您已经引用的那样。

有时您可能希望在调用中使用明确的名称,这将MyClass.Factory.create()在您的示例中。可能出于命名空间的原因。

我也没有看到很多理由来命名一个伴生对象。除非您关心 Java 与 Kotlin 代码的互操作。然后,您需要显式地编写同伴名称。

您可能关心名称的另一个原因是,当您在其上定义扩展函数时:

  fun MyClass.Companion.ext() = "myext"

在这种情况下,当它具有类似的名称时会更清楚,Factory通过扩展添加特定的工厂方法。

于 2017-08-24T05:46:59.080 回答
1

但是,我没有看到使用伴随对象名称的示例。

class Person(val name: String) { companion object Loader {
fun fromJSON(jsonText: String): Person = ... }
}
>>> person = Person.Loader.fromJSON("{name: 'Dmitry'}") >>> person.name
Dmitry
>>> person2 = Person.fromJSON("{name: 'Brent'}") >>> person2.name
Brent
于 2017-08-24T08:21:25.803 回答