Scala Classes & Constructors

Hi Friends,
In this post of The Online Scala Tutorial Series we will be talking about Scala Classes and Scala constructors. We will see the way we can create Scala class instance and the way to define the constructors. The Scala constructor has some interesting properties that might seem little strange for a regular Java programmer. Scala constructors come in two different flavors : Primary Constructors and Auxiliary Constructors. Let's have a look at them here.



Scala Class & The Default Constructor:


Below is an example of how we write a Class.


class MessagePrinter {
    def printMessage(message : String) = println(message)
}


We have created a Scala Class called as MessagePrinter. The class has a method printMessage, which takes the message as an argument and simply prints it. Notice, till now there is no constructor defined here, which means Scala is implicitly adding a default (no argument) constructor in the Class. In the below example, let's have a look at how to instantiate MessagePrinter and print a message with that instance.



scala> var printer  = new MessagePrinter()
print: MessagePrinter = MessagePrinter()

scala> print.printMessage("How are you doing today?")
How are you doing today? // final output


Look at the first line, we have created a MessagePrinter instance with a new keyword and assigned it to a var printer. Notice one thing that we have not provided an explicit data type of printer. That is because of Scala's type inference mechanism. Scala's type inference will automatically look at the RHS of the expression, find out the type and assume the type of the variable (LHS) it is being assigned to. Then, on the next line we are simply calling printMessage method on the newly created instance. We are passing a message to the method and see the output is being printed correctly.


Let's add an instance variable to the class. Suppose we want to greet a specific person with his name. We'll have a fixed name as an instance variable in the class. The printMessage method will take the message and print it along with the name.



class MessagePrinter {
    var name : String = "Tom Hanks"
    def printMessage(message : String) = println(message + " " + name)
}


Below is a way to call the method and the output


scala> var print  = new MessagePrinter()
print: MessagePrinter = MessagePrinter@1fe51ef8

scala> print.printMessage("Welcome to Scala Mr.")
Welcome to Scala Mr. Tom Hanks // final outout



The Custom Constructors:


The last example was obvious, wasn't it?
Okay! now, we don't want to restrict our MessagePrinter to a specific user. Rather we want to create a separate instance of MessagePrinter for each user. In that case we will have to externally inject the person name from outside while creating the instance. We will use a parameterized constructor to do this. Now, here it becomes non-obvious for a typical Java Programmer. Let's have look at below modification where we have added a constructor which take an argument.



class MessagePrinter (name : String) {
    def printMessage(message : String) = println(message + " " + name)
}


Yes, this is a way to define a constructor in Scala. It looks like the class is accepting some arguments just like methods do, and it makes sense too. But the interesting thing is the instance variable is now gone. We don't need to write a contractor with body and map the constructor arguments to the actual instance variables. Here in the above code, where the class is taking an argument name is treated as an instance variable of this class. The printMessage method can still refer to and use the instance variable name in the same way it was doing in the last example we saw.

Let's try calling this.


scala> var print = new MessagePrinter("Tom Hanks")
print: MessagePrinter = MessagePrinter@b86cb11

scala> print.printMessage("Welcome to Scala Mr.")
Welcome to Scala Mr. Tom Hanks //final output



The only thing changed here is the way we created MessagePrinter. This time we are externally providing the name of the person and no wonder calling printMessage would print the same message.



The Primary Constructor:


The constructor we saw above is called as a primary constructor. Each class will have only one primary constructor. Only the primary constructor will have ability to invoke superclass constructors. We wrote a primary constructor which accepts a variable which is automatically registered as an instance variable of the class. What if we have to do some additional thing in constructor, other than defining the instance variables? Where to put such additional lines? Answer is, when we have a primary constructor in a class the whole class (except method bodies) will be treated as the body of the primary constructor. Let's see it in below example.



class MessagePrinter (name : String) {
    println("Primary Constructor is called with argument = " + name)
    def printMessage(message : String) = println(message + " " + name)
}


Let's instantiate it.


scala> var print = new MessagePrinter("Tom Hanks")
Primary Constructor is called with argument = Tom Hanks
print: MessagePrinter = MessagePrinter@28907997


It printed the line. The code we put in the class body is considered as a part of the primary constructor body and that pretty amazing.

Now, some of you might be thinking, we have bound our class to a specific constructor. Sometimes a class might have multiple constructors and while calling it we might choose a way to instantiate a class by calling a specific constructor out of the available ones. Can't we do that in Scala?
Yes, we can. Such add-on constructor are called as Auxiliary Constructors



Auxiliary Constructors:


We have seen what is a Primary Constructor. We might sometimes need multiple constructors to be introduced, in Scala, all of such constructors are called as Auxiliary contractors. We can have multiple auxiliary constructors in a class. The basic condition is, each auxiliary constructor must call the primary constructor (or another auxiliary constructor) as a first line of its code. That means each auxiliary constructor would directly or indirectly call the primary constructor and the primary constructor would be the actual constructor constructing the class instance. Let's see how to write an Auxiliary Constructor.

Let's consider client want to instantiate the MessagePrinter but it has the user name is splitter format, first name and last name. Instead of asking client to concatenate the names into single name and call the primary constructor, we want to let them pass the names in two parts and then we will concatenate it. See the below example.



class MessagePrinter (name : String) {
    println("Primary Constructor is called with argument = " + name) 
    def this (firstName: String, lastName : String) = {
       this (firstName + " " + lastName)
       println("Two argument auxiliary Constructor is called")
    }
    def printMessage(message : String) = println(message + " " + name)
}


The Auxiliary Constructors are always defined with name this. The constructor looks like any method definition with the difference of the name which is this and an absence of the return type. As a first line the auxiliary contractor is calling the primary contractor we have. Let's try calling the Auxiliary contractor this time.



scala> var printer = new MessagePrinter("Tom", "Hanks")
Primary Constructor is called with argument = Tom Hanks
Two argument auxiliary Constructor is called
printer: MessagePrinter = MessagePrinter@47287f45


As a first line the Primary Constructor message is displayed and then the one from Auxiliary Constructor. As said earlier each Auxiliary Constructor must call the primary constructor or another Auxiliary constructor as a very first line of its body. This way the primary constructor will be called somewhere in the turn. Is is applicable even if we don't have any Primary Constructor. If we don't have a Primary constructor Scala will implicitly add a no argument constructor as a Primary Constructor and the Auxiliary constructors must call this() (or other auxiliary constructor).


That's pretty much for today. Let's meet soon with some more interesting features of the Scala Language. Take Care!
Post a Comment