带有伴随对象的类与具有相同名称的类和对象之间有什么区别? [英] What's the difference between a class with a companion object and a class and object with the same name?

查看:101
本文介绍了带有伴随对象的类与具有相同名称的类和对象之间有什么区别?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

可以将Scala类的伴侣对象"视为具有与该类相同的完全限定名称的单例对象(即,在同一包中具有相同的名称).它们用于保存该类的所有实例通用的实用程序功能,以代替Java的static方法.

A Scala class's "companion object" 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 methods.

但是,在文档中的各个地方以及有疑问的地方,它都说必须在同一个编译单元中定义伴随对象.例如,必须在同一个文件中定义它们. 伴侣对象无法为Java对象定义;在REPL中,它们必须在同一输入行上定义,因此显示警告消息:

However, in various places in the docs and in questions, it say that companion objects must be defined in the same compilation unit. For example, they must be defined in the same file; companion objects cannot be defined for Java objects; in the REPL, they must be defined on the same input line, hence the warning message:

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.

这意味着在带有其伴随对象的类与具有相同(完全限定)名称的类和对象之间必须存在区别.这个区别是什么?

This implies that there must be a distinction between a class with its companion object, and just a class and object with the same (fully qualified) name. What is this distinction?

推荐答案

我们将其称为类class SomeClass(尽管它也可以是例如trait).

Let's call the class class SomeClass (though it could also be e.g. a trait).

伴随对象(object SomeClass)的方法可以访问class SomeClass实例的私有方法/数据.

Methods of the companion object (object SomeClass) have access to private methods/data of instances of class SomeClass.

如果同伴对象仅使用类的公共接口(例如,仅定义常量),则没有实际区别.但是在许多情况下,让实用程序函数访问私有成员很有用.例如,object SomeClass可以定义一种工厂方法apply,该方法设置class SomeClass的私有成员,而不必在公共接口中公开设置器.因此,在这种情况下,您必须通过将object SomeClass的定义放在与class SomeClass相同的编译单元中来定义伴随对象.

If your companion object only uses the public interface of your class (e.g. just defines constants), there's no practical difference. But there are a number of cases where it's useful to let utility functions access private members. For example, object SomeClass could define a factory method apply that sets up private members of class SomeClass, without having to expose setters in the public interface. In such cases, you must therefore define a companion object by putting the definition of object SomeClass in the same compilation unit as class SomeClass.

另一个不同之处是,编译器会在类型(和其超类型).因此,如果使用的隐式转换是在class SomeClass的代码中定义的,则必须在伴随对象中对其进行定义.

Another difference is that the compiler searches for implicits in companion objects of a type (and its supertypes). So if you are using implicit conversions you define in the code of class SomeClass, you must define them in the companion object.

两者的结合也解释了相同的编译单元限制.

The combination of the two also explains the same-compilation-unit restriction.

  • scalac在知道它要调用的class SomeClass的私有成员之前,无法编译object SomeClass.
  • scalac在知道其隐式调用之前无法编译class SomeClass.因此,伴随对象必须不迟于class SomeClass进行编译.
  • scalac can't compile object SomeClass until it knows what private members of class SomeClass it calls.
  • scalac can't compile class SomeClass until it knows what implicits it calls. So the companion object must be compiled no later than class SomeClass.

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

It follows they must be compiled at the same time. Further, the current compiler apparently compiles separate files separately (cf. the lack of support for splitting classes across multiple files), restricting it to the same compilation unit.

这篇关于带有伴随对象的类与具有相同名称的类和对象之间有什么区别?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆