Scala 类的“伴生对象”可以被视为具有与类相同的完全限定名称的单例对象(即,相同的名称,在同一个包中)。它们用于保存类的所有实例共有的实用函数,作为 Java 的 static
的替代品。方法。
但是,在文档和问题的各个地方,它说必须在同一编译单元中定义伴随对象。例如,它们必须在同一个文件中定义; companion objects cannot be defined for Java objects ; in the REPL, they must be defined on the same input line ,因此警告消息:
warning: previously defined class Foo is not a companion to object Foo.
Companions must be defined together; you may wish to use :paste mode for this.
这意味着一个类与其伴生对象之间必须有区别,而只是一个类和具有相同(完全限定)名称的对象。这个区别是什么?
最佳答案
让我们调用类class SomeClass
(尽管它也可以是例如 trait
)。
私有(private)成员(member)
伴随对象的方法(object SomeClass
)可以访问私有(private)方法/数据 class SomeClass
的实例数.
如果您的伴生对象仅使用您的类的公共(public)接口(interface)(例如,仅定义常量),则没有实际区别。但是在许多情况下,让实用程序函数访问私有(private)成员很有用。例如,object SomeClass
可以定义工厂方法apply
设置 class SomeClass
的私有(private)成员,而不必在公共(public)接口(interface)中公开 setter 。因此,在这种情况下,您必须通过将 object SomeClass
的定义定义为伴随对象。在与 class SomeClass
相同的编译单元中.
另一个区别是 the compiler searches for implicits in companion objects of a type (and its supertypes) .因此,如果您使用在 class SomeClass
的代码中定义的隐式转换,您必须在伴随对象中定义它们。
评论
两者的结合也解释了相同编译单元的限制。
scalac
无法编译 object SomeClass
直到它知道 class SomeClass
的私有(private)成员是什么它调用。 scalac
无法编译 class SomeClass
直到它知道它所隐含的内容。所以伴生对象的编译时间不得晚于 class SomeClass
. 因此它们必须同时编译。此外,当前的编译器显然单独编译单独的文件(参见缺乏对跨多个文件拆分类的支持),将其限制在同一个编译单元中。
关于oop - 具有伴随对象的类与具有相同名称的类和对象之间有什么区别?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11604320/