Scala 类的“伴生对象”可以被视为具有与该类相同的完全限定名称的单例对象(即相同的名称,在同一包中)。它们用于保存类的所有实例共有的实用函数,作为 Java 的替代品static
方法。
然而,在文档和问题的不同地方,它说伴生对象必须在同一编译单元中定义。例如,它们必须定义在同一个文件中;不能为 Java 对象定义伴生对象 https://stackoverflow.com/questions/4921827/in-scala-how-can-i-define-a-companion-object-for-a-class-defined-in-java; 在 REPL 中,它们必须在同一输入行上定义 https://stackoverflow.com/questions/6919965/companion-object-cannot-access-private-variable-on-the-class,因此出现警告消息:
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
).
私人会员
伴随对象的方法(object SomeClass
) 可以访问私有方法/数据的实例数class SomeClass
.
如果您的伴生对象仅使用类的公共接口(例如,仅定义常量),则没有实际差异。但在许多情况下,让实用程序函数访问私有成员是很有用的。例如,object SomeClass
可以定义一个工厂方法apply
设置私人成员class SomeClass
,而不必在公共接口中公开设置器。因此,在这种情况下,您必须通过将以下定义定义为伴生对象:object SomeClass
在同一个编译单元中class SomeClass
.
另一个区别是编译器在类型(及其超类型)的伴生对象中搜索隐式 http://docs.scala-lang.org/tutorials/FAQ/finding-implicits.html#companion_objects_of_a_type。因此,如果您使用隐式转换,则在代码中定义class SomeClass
,您必须在伴生对象中定义它们。
Comments
两者的结合也解释了相同编译单元的限制。
-
scalac
无法编译object SomeClass
直到它知道私有成员是什么class SomeClass
它呼唤。
-
scalac
无法编译class SomeClass
直到它知道它调用的隐式是什么。因此,伴生对象必须在不晚于class SomeClass
.
因此它们必须同时编译。此外,当前的编译器显然是单独编译单独的文件(参见缺乏对跨多个文件拆分类的支持),将其限制为同一编译单元。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)