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

标签 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.

这意味着一个类与其伴生对象之间必须有区别,而只是一个类和具有相同(完全限定)名称的对象。这个区别是什么?

最佳答案

让我们调用类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/

    相关文章:

    javascript - 使用 addEventListener 调用 onclick 方法

    java - Java 类可以拥有类型本身的实例吗?

    c++ - 使用通用基础和布局有效的 C++ 来转换非多态结构吗?

    scala - 在 intellij 中使用 scala 项目缓慢编译 play 框架

    scala - 将笛卡尔坐标组分组到apache Spark中的单元格

    c - 如何用 extern 解决新声明的多个先前声明?

    c++ - 使用 reinterpret_cast 将函数强制转换为 void*,为什么不违法?

    php - 在 PHP 中使用带有作用域解析运算符的变量

    php - 在另一个类方法中创建类对象给出 fatal error

    scala - Elastic4s-与Elasticsearch集群的HTTPS连接