伴随对象的文档包含以下示例
class MyClass {
companion object Factory {
fun create(): MyClass = MyClass()
}
}
此处Factory
是伴随对象的名称。然后它继续说:
可以省略伴随对象的名称,在这种情况下,将使用名称
Companion
:
但是,我看不到使用伴随对象名称的示例。
由于每个类只能有一个伴随对象(否则会出现Only one companion object is allowed per class
错误(,因此这个名称对我来说就像一些非常无用的语法糖。
伴随对象的名称实际上可以用于什么? 为什么人们会费心为它使用任何名称?
您可以使用同伴的名称,如下所示:
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
好吧,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()
}
如果您不使用显式名称,则同伴名称为Companion
,因此可以省略它,就像您已经引用的那样。
有时,您可能希望在调用中使用显式名称,这在您的示例中MyClass.Factory.create()
。也许出于命名空间的原因。
我也看不出有很多理由来命名一个伴随对象。除非你关心 Java 与 Kotlin 代码的互操作。然后,您需要明确写入同伴姓名。
您可能关心该名称的另一个原因是,当您在其上定义扩展函数时:
fun MyClass.Companion.ext() = "myext"
在这种情况下,当它有一个像Factory
这样的名称时会更清楚,通过扩展添加特定的工厂方法。
但是,我看不到使用伴随对象名称的示例。
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