Scala类的“伴随对象”可以被视为单个对象,具有与该类相同的完全限定名称(即同一个名称,在同一个包中)。它们用于保存类的所有实例共有的实用程序函数,以替代Java static
方法。
但是,在文档和问题的不同位置,它表示必须在同一编译单元中定义伴随对象。例如,它们必须在同一个文件中定义; 无法为Java对象定义伴随对象; 在REPL中,它们必须在同一输入行上定义,因此警告信息:
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
(虽然它也可能是例如a trait
)。
私人会员
伴侣对象的方法(object SomeClass
) 可以访问私有方法/数据 的实例 class SomeClass
。
如果您的伴随对象仅使用您的类的公共接口(例如,只定义常量),则没有实际区别。但是在许多情况下,让实用程序函数访问私有成员是有用的。例如, object SomeClass
可以定义工厂方法 apply
设立的私人成员 class SomeClass
,而不必在公共接口中公开setter。在这种情况下,您必须通过放置定义来定义伴随对象 object SomeClass
在同一个编译单元中 class SomeClass
。
另一个不同之处在于 编译器在类型的伴随对象(及其超类型)中搜索implicits。因此,如果您使用隐式转换,则在代码中定义 class SomeClass
,您必须在伴侣对象中定义它们。
注释
两者的结合也解释了相同的编译单元限制。
scalac
无法编译 object SomeClass
直到它知道什么是私人成员 class SomeClass
它叫。
scalac
无法编译 class SomeClass
直到它知道它所调用的内容。因此,伴随对象必须不迟于编译 class SomeClass
。
它遵循它们必须同时编译。此外,当前编译器显然单独编译单独的文件(参见缺少对跨多个文件拆分类的支持),将其限制为相同的编译单元。
我们打电话给全班 class SomeClass
(虽然它也可能是例如a trait
)。
私人会员
伴侣对象的方法(object SomeClass
) 可以访问私有方法/数据 的实例 class SomeClass
。
如果您的伴随对象仅使用您的类的公共接口(例如,只定义常量),则没有实际区别。但是在许多情况下,让实用程序函数访问私有成员是有用的。例如, object SomeClass
可以定义工厂方法 apply
设立的私人成员 class SomeClass
,而不必在公共接口中公开setter。在这种情况下,您必须通过放置定义来定义伴随对象 object SomeClass
在同一个编译单元中 class SomeClass
。
另一个不同之处在于 编译器在类型的伴随对象(及其超类型)中搜索implicits。因此,如果您使用隐式转换,则在代码中定义 class SomeClass
,您必须在伴侣对象中定义它们。
注释
两者的结合也解释了相同的编译单元限制。
scalac
无法编译 object SomeClass
直到它知道什么是私人成员 class SomeClass
它叫。
scalac
无法编译 class SomeClass
直到它知道它所调用的内容。因此,伴随对象必须不迟于编译 class SomeClass
。
它遵循它们必须同时编译。此外,当前编译器显然单独编译单独的文件(参见缺少对跨多个文件拆分类的支持),将其限制为相同的编译单元。