This is an excerpt from the Scala Cookbook (partially modified for the internet). This is Recipe 4.4, “How to define a private primary constructor in Scala.”
Problem
You want to make the primary constructor of a Scala class private, such as to enforce the Singleton pattern.
Solution
To make the primary constructor private, insert the private
keyword in between the class name and any parameters the constructor accepts:
// a private no-args primary constructor class Order private { ... ------- // a private one-arg primary constructor class Person private (name: String) { ... -------
As shown in the REPL, this keeps you from being able to create an instance of the class:
scala> class Person private (name: String) defined class Person scala> val p = new Person("Mercedes") <console>:9: error: constructor Person in class Person cannot be accessed in object $iw val p = new Person("Mercedes") ^
Discussion
A simple way to enforce the Singleton pattern in Scala is to make the primary constructor private, then put a getInstance
method in the companion object of the class:
class Brain private { override def toString = "This is the brain." } object Brain { val brain = new Brain def getInstance = brain } object SingletonTest extends App { // this won't compile // val brain = new Brain // this works val brain = Brain.getInstance println(brain) }
You don’t have to name the accessor method
getInstance
; it’s only used here because of the Java convention.
A companion object is simply an object that’s defined in the same file as a class, where the object and class have the same name. If you declare a class named Foo
in a file named Foo.scala, and then declare an object named Foo
in that same file, the Foo
object is the companion object for the Foo
class.
A companion object has several purposes, and one purpose is that any method declared in a companion object will appear to be a static method on the object. See Recipe 6.6 for more information on creating the equivalent of Java’s static methods, and Recipe 6.8 for examples of how (and why) to define apply
methods in a companion object.
Utility classes
Depending on your needs, creating a private class constructor may not be necessary at all. For instance, in Java you’d create a file utilities class by defining static methods in a Java class, but in Scala you do the same thing by putting all the methods in a Scala object:
object FileUtils { def readFile(filename: String) = { // code here ... } def writeToFile(filename: String, contents: String) { // code here ... } }
This lets consumers of your code call these methods like this:
val contents = FileUtils.readFile("input.txt") FileUtils.writeToFile("output.txt", content)
Because only an object is defined, code like this won’t compile:
val utils = new FileUtils // won't compile
So in this case, there’s no need for a private class constructor; just don’t define a class.
this post is sponsored by my books: | |||
#1 New Release |
FP Best Seller |
Learn Scala 3 |
Learn FP Fast |