Static factory methods, in Scala!

Factory

Context – Static factory methods in Java
Static factory methods in Java were popularized by Josh Bloch in Effective Java, item 1. A simple introduction to them is to use a couple examples that you already know, from the standard Java API:

  int x = 100;
  Double xD = Double.valueOf(100);

Here a “Double” object is constructed using the static factory method “valueOf.” If you look at the Java source for Double, you can see that valueOf has a method signature that is “public static” and that it returns an instance of a class. Those two things together are what makes it a “static” “factory” method.

I don’t think that static factory methods always have to return an instance of the class that they are defined within. Sometimes static factory methods are utility methods used to convert from one type to another. For example, let’s say we have an array and we want a list. Longtime Java devs will remember the Arrays.asList() method:

  String[] names = {"Jane", "Harold", "Barry", "Wanda", "Theresa"};
  List namesList = Arrays.asList(names);

Arrays.asList() is a static factory method also in my opinion.

Scala doesn’t have the static keyword
Switching gears slightly, if you are a Java developer coming into the Scala world, you will find there is no direct equivalent to the “static” keyword in Scala. You have to think of things quite a bit differently. In Scala, the language designers believed that it was not OO to have static methods hanging about. Instead, they built singletons into the language as a substitute for this purpose. You can argue with it all you want, but there it is. At least they are not as hard to define as singletons in Java or C++ are.

Scala Singletons are Simple
To create a “singleton” in Scala, simply use the object keyword.

object StaticMethods {
     def hello(): Unit = {
       println("Hello, world!")
     }
}

Now you can run…

StaticMethods.hello

…which will output:

Hello, world!

So the usage of an object/singleton method (ClassName.methodCall) ends up looking rather a lot like a static method call in Java.

Static fields and methods in classes with instances, in Java
As you may know this singleton approach by no means provides like-for-like functionality to Java’s static keyword. It may seem rather annoying to a Java developer because there are situations where Java developers like to have a normal class with instances as well as static methods and fields. With static fields, they can keep track of certain things that pertain to all instances of a class. Java devs also sometimes like to mark their constructors private so that their static factory methods are the only possible way to construct an instance of a particular class.

Why you might want to do all these things is best shown in the following simple example. Here we create a class called “Person” which stores a person’s first and last name. It also stores an integer identifier which automatically increments every time a new instance of Person is created.

If you want to try this out and see the id value get automatically incremented, you can run something like:

  Person mickey = Person.create("Mickey", "Mantle");
  Person lou = Person.create("Lou", "Gehrig");
  System.out.println(mickey.getName() + " has id " + mickey.getId());
  System.out.println(lou.getName() + " has id " + loud.getId());
  System.out.println("Next id will be " + Person.NEXT_ID);

And your output will be:

Mickey Mantle has id 0
Lou Gehrig has id 1
Next id will be 2

Another example of this that Java devs might remember is the Java trail on classes, where the Bicycle class keeps track of the number of bicycles there are.

Scala Companion Objects
So since there is no static keyword in Scala, and there is no direct equivalent, is it not possible to achieve this?

Actually Scala does provide this same functionality. You just have to do it in a quite different manner, using a “companion object.”

A companion object is an object that has the same name as a class and is defined together with it in the same file. This looks like the below code.

There are four important pieces to this, marked with comments above:

  1. The constructor is marked private in the class declaration.
  2. The apply method is provided. In Scala, “apply” is syntactic sugar which allows any call to a class which lacks a specific method call to be directed to the apply method.
  3. The companion object is defined with the same name as the class and placed in the same file. Instead of “class,” you use the “object” keyword.
  4. The “create” method is nothing special other than being a method that is part of a companion object. The call to “new Person” in the create method is actually a call to the apply method.

The end result / usage is pretty much the same as having a class with static methods and fields. If you open the REPL, you can experiment with the above by using paste mode to paste it in. You may be familiar with “:load” in the REPL but that doesn’t seem to work when companion objects are used. Paste mode works, though. Once in the REPL, just type “:paste”, paste the above snippet, then hit Ctrl+D. Now you can use the Person.create static factory method:

scala> val mickey = Person.create("Mickey","Mantle")
mickey: Person = Person@265bd645

scala> val lou = Person.create("Lou","Gehrig")
lou: Person = Person@37264b74

scala> println(mickey.getName() + " has id " + mickey.getId())
Mickey Mantle has id 0

scala> println(lou.getName() + " has id " + lou.getId())
Lou Gehrig has id 1

scala> println("Next id will be " + Person.nextId)
Next id will be 2

Factory methods in Scala
As you can see there is equivalent functionality in Scala to provide the static factory method approach that you might be used to in Java. Actually, with the apply method and companion objects, a whole new world opens up which I might get into in a future post. One example of what I mean is Alvin Alexander’s approach to the abstract factory pattern (something different than static factory methods) shown over on his blog.

Usually, you can use just a companion object without also using a private constructor or apply method any time you want to add what you might know as “static factory methods” as a Java developer. Here is a simplified quick example you might like as a summary:

object Letter{
  def asChar(l: Letter): Char = {
    val pos = 'a' + l.index - 1
    if(pos >= 'a' && pos <= 'z')
     pos.toChar
    else
      'a'
   }
}

class Letter(val index: Int)

With this, you could call "Letter.asChar()" on any letter, and it will return the appropriate Letter:

scala> Letter.asChar(new Letter(3))
res1: Char = c

One thought on “Static factory methods, in Scala!

Leave a Reply

Your email address will not be published. Required fields are marked *