具有伴随对象的类与具有相同名称的类和对象之间的区别是什么?

时间:2012-07-22 22:01:06

标签: oop scala language-lawyer scala-java-interop companion-object

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.

这意味着必须区分具有其伴随对象的类,以及具有相同(完全限定)名称的类和对象。这是什么区别?

1 个答案:

答案 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之前编译伴随对象。

因此必须同时编译它们。此外,当前编译器显然单独编译单独的文件(参见缺少对跨多个文件拆分类的支持),将其限制在同一个编译单元。