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.
这意味着必须区分具有其伴随对象的类,以及具有相同(完全限定)名称的类和对象。这是什么区别?
答案 0 :(得分:16)
我们打电话给班级class SomeClass
(虽然它也可以是例如trait
)。
配套对象(object SomeClass
)的方法可以访问class SomeClass
个实例的私有方法/数据。
如果您的伴侣对象仅使用您的类的公共接口(例如,只定义常量),则没有实际区别。但是在许多情况下,让实用程序函数访问私有成员是有用的。例如,object SomeClass
可以定义工厂方法apply
,用于设置class SomeClass
的私有成员,而不必在公共接口中公开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
私有成员为止。scalac
无法编译class SomeClass
,直到它知道它所调用的内容为止。因此,必须在class SomeClass
之前编译伴随对象。因此必须同时编译它们。此外,当前编译器显然单独编译单独的文件(参见缺少对跨多个文件拆分类的支持),将其限制在同一个编译单元。