tags:

views:

1097

answers:

4

I am new to Scala and may be missing something very basic but I couldn't think of 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.

Can anyone please explain ?

+9  A: 

The companion object basically provides a place where one can put 'static' methods. In fact, that's exactly how the compiler does it. Further more, a companion object, or companion module, has full access to the class members, including private ones.

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

Saem
+6  A: 

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).

Fabian Steeg
+6  A: 

...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 EffectiveJava about telescoping cnstrct)

  3. you are able to decide which derived class you want to create insted of the abstract (accompanied) one

Example code:

abstract class AbstractClass;
class RealThing(s: String) extends AbstaractClass;
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 becouse 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.

Szymon Jachim
A: 

Companion objects are useful for storing state and methods that are common to all instances of an object 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
Craig P. Motlin