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.
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?
A Companion object is initialized when the class is loaded (typically the first time it's referenced by other code that is being executed) whereas Object declarations are initialized lazily, when accessed for the first time.
Companion courses are a pair of courses (or a group of courses) that should be studied together. Companion courses can either be studied all together in the same semester, or in separate semesters (i.e. one companion can be studied before another).
Class vs ObjectA class is a blueprint for declaring and creating objects. An object is a class instance that allows programmers to use variables and methods from inside the class. Memory is not allocated to classes. Classes have no physical existence.
A class is a template for objects. A class defines object properties including a valid range of values, and a default value. A class also describes object behavior. An object is a member or an "instance" of a class.
Let's call the class class SomeClass
(though it could also be e.g. a trait
).
Methods of the companion object (object SomeClass
) have access to private methods/data of instances of 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
.
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
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With