Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the rationale behind having companion objects in Scala?

Is there a case where a companion object (singleton) for a class is needed? Why would I want to create a class, say Foo and also create a companion object for it?

like image 992
Rahul Avatar asked Mar 04 '09 08:03

Rahul


People also ask

What is purpose of companion object in Scala?

A companion object is an object that's declared in the same file as a class , and has the same name as the class. A companion object and its class can access each other's private members. A companion object's apply method lets you create new instances of a class without using the new keyword.

What is the advantage of companion object in Scala?

Advantages of Companion Objects in Scala Companion objects provide a clear separation between static and non-static methods in a class because everything that is located inside a companion object is not a part of the class's runtime objects but is available from a static context and vice versa.

What is the necessity for singleton and companion objects?

A singleton object provides an entry point to your program execution. If you do not create a singleton object in your program, then your code compile successfully but does not give output. So you required a singleton object to get the output of your program. A singleton object is created by using object keyword.

Why do we use companion object as a kind of replacement for Java static fields in Kotlin?

Solution: companion objectThe ability to extend interfaces and classes is one of the features that sets the companion objects apart from Java's static functionality. Also, companions are objects, we can pass them around to the functions and assign them to variables just like all the other objects in Kotlin.


5 Answers

The companion object basically provides a place where one can put "static-like" methods. Furthermore, a companion object, or companion module, has full access to the class members, including private ones.

Companion objects are great for encapsulating things like factory methods. Instead of having to have, for example, Foo and FooFactory everywhere, you can have a class with a companion object take on the factory responsibilities.

like image 90
Saem Avatar answered Oct 13 '22 00:10

Saem


Companion objects are useful for storing state and methods that are common to all instances of a class but they do not use static methods or fields. They use regular virtual methods which can be overridden through inheritance. Scala truly has nothing static. There are lots of ways you can use this but here's a simple example.

abstract class AnimalCounter
{
    var animals = 0

    def name: String

    def count()
    {
        animals += 1
        println("%d %ss created so far".format(animals, name))
    }
}

abstract class Animal
{
    def companion: AnimalCounter
    companion.count()
}

object Dog extends AnimalCounter
{
    val name = "dog"
}

class Dog extends Animal
{
    def companion = Dog
}

object Cat extends AnimalCounter
{
    val name = "cat"
}

class Cat extends Animal
{
    def companion = Cat
}

Which produces this output:

scala> new Dog
1 dogs created so far

scala> new Cat
1 cats created so far

scala> new Dog
2 dogs created so far

scala> new Cat
2 cats created so far
like image 24
Craig P. Motlin Avatar answered Oct 13 '22 01:10

Craig P. Motlin


...and it's a good place to store static factory methods (not that DP) for accompanied classes. If you name those overloaded factory methods apply(/.../) you will be able to create/initialize you class

  1. without 'new' (not really that important)

  2. with different possible sets of parameters (compare to what Bloch writes in Effective Java about telescoping constructor)

  3. with the ability to to decide which derived class you want to create instead of the abstract (accompanied) one

Example code:

abstract class AbstractClass;
class RealThing(s: String) extends AbstractClass;
class AlternativeThing(i: Int) extends AbstractClass;
object AbstractClass {
  def apply(s: String) = {
    new RealThing(s)
  }
  def apply(i: Int) = {
    new AlternativeThing(i)
  }
}

// somewhere else you can
val vs = AbstractClass("asdf")  // gives you the RealThing wrapped over string
val vi = AbstractClass(123)  // gives you AlternativeThing wrapped over int

I wouldn't call the object/base class AbstractXxxxx because it doesn't looks bad: like creating something abstract. Give those names a real meaning. Consider using immutable, method less, case classes and seal the abstract base class.

like image 23
Szymon Jachim Avatar answered Oct 13 '22 01:10

Szymon Jachim


In addition to the things Saem said in his reply, the Scala compiler also looks for implicit conversions of types in the corresponding companion objects (of either the source or the target), so the conversions don't need to be imported.

About the reason for singleton objects in general Programming in Scala says:

As mentioned in Chapter 1, one way in which Scala is more object-oriented than Java is that classes in Scala cannot have static members. Instead, Scala has singleton objects (p. 65).

like image 41
Fabian Steeg Avatar answered Oct 12 '22 23:10

Fabian Steeg


I always see companion objects as a bridge to write both functional and object oriented code in Scala. Many times we just need pure functions which take some input and provide a processing result. Putting those relevant functions in the companion object makes it easy to look up and use, for myself as well as some one building on top of my code.

Moreover, it is a language provided feature to write the singleton pattern without doing anything. This is especially useful when you need a singleton to encapsulate a delegator for the life of JVM. For example, writing a simple HTTP client library in Scala where you can encapsulate an underlying Java implementation based delegator and let consumers of your API live in pure world.

like image 27
Gaurav Abbi Avatar answered Oct 12 '22 23:10

Gaurav Abbi