首页 文章

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

提问于
浏览
11

一个Scala类's 2638380 can be viewed as a singleton object with the same fully qualified name as the class (i.e. same name, in same package). They are used to hold utility functions common to all instances of the class, as a replacement for Java' s 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 回答

  • 16

    让我们调用类 class SomeClass (尽管它也可以是例如 trait ) .

    私人会员

    伴随对象的方法( object SomeClasshave access to private methods/data class SomeClass 的实例 .

    如果您的伴随对象仅使用您的类的公共接口(例如,只定义常量),那么's no practical difference. But there are a number of cases where it'对于让实用程序函数访问私有成员很有用 . 例如, 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 之前编译伴随对象 .

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

相关问题