Welcome back. We already learned some basics of a Scala class definition. Now it's time to look
at the constructors.
In
this lesson, I will talk about following items.
- Default Constructor
- Primary Constructor
- Auxiliary Constructor
Default Constructor
Let's start with the default constructor.
Every Scala class comes with a default primary contractor that doesn't take any argument.
So, if you look at the above example, you don't see a code for a constructor. We haven't defined any constructor. But there is a default constructor that doesn't take any argument. And that's why we can instantiate this class using an empty argument list.
If you want to change the default constructor, you have two options. Primary constructor and an auxiliary constructor. Let's talk about the primary constructor.
Primary Constructor
I want to take you back to the Java world and build Scala concept on top of that. So, let's look at a typical Java class.
In the above code, we have a public class. We declare some private variables. Create a
constructor. Then we create a get
and a set method. Right?
Scala's philosophy is to save you from unnecessary typing and help you create a concise
code.
On that note, we already learned that if we make the radius public, we can get rid of those two
get/set
methods. Scala compiler will automatically generate those methods. We already learned that.
Right?
We also learned that there is no need to type the public modifier for the class. If we remove
all
those things, we are left with below lines.
Scala creators said, why the hell you want to type the class name and curly braces once again for defining a constructor? We already typed the class name for the class definition, so pass the arguments right there. We already have a pair of curly braces for the class, so use that as the body of your constructor. Amazing. Isn't it? If we make those changes, we have a Scala class with a primary constructor.
The Circle is your class name and the constructor as well. If you don't pass any arguments,
Scala will give you a constructor
with no arguments. We call that a default constructor. If you pass some arguments, Scala will
give
you a constructor with those arguments. We call that one a primary constructor.
The part, inside the pair of curly braces is the class body as well as a constructor body.
And
hence, Scala executes all statements in the class definition.
But that is not enough. Scala doesn't stop there. It goes one step further to help you
create
a concise code. Let me show you that as well.
Instantiate the above class and check the list of methods. Do you notice something unusual?
We
have a reader and a write for the radius. I expected that because I declared a public var. But
why
the hell we have a reader and a writer method for the
newRadius. It looks like Scala took the
newRadius
and made it a public var. And that's why we see a reader and a writer for the
newRadius.
What does that mean? That means, there was no need to declare the radius and initialize it
with
the constructor parameter. I should have declared my class like this.
That's it. And Scala takes care of declaring a variable for radius, initialize it with the constructor parameter and also create a reader and a writer method. So, the one line of Scala code is equal to those several lines of Java code. Amazing. Isn't it?
How a var and val are different in Scala Constructor
Let me ask you few questions. We used a var type argument for the primary constructor. What happens if we change it to val?
We learned this in the earlier lesson. The
val is a read-only type. So, Scala won't create a writer method. Next question. What
if
I don't even want a reader? How to do that?
Remember? I asked that question in the earlier lesson. The answer is still same. Make it a
private val
. Scala will create the reader, but it will make that reader private.
There is another alternative to achieve the same. Don't tell Scala about the type.
Above code doesn't specify anything. Neither a val nor a var. As a result, Scala won't create a reader or a writer. It is as good a private val. However, in this case, Scala makes the radius an object-private field. I hope you understand the difference between a private and an object-private field.
Auxiliary Constructor
So far so good. But when I create a primary constructor, I lose the default constructor. The
constructor with no arguments
is the default constructor. If you define some arguments, it becomes the primary constructor,
and
you lose the constructor that takes no arguments. How do you fix that?
In some cases, you might need multiple constructors. Let's try to understand that with the
help
of an example.
I have a requirement to create a class for a Box. The Box should have three instance
variables.
- Width
- Height
- Depth
We also need three different constructors.
- A default constructor that doesn't take any argument. The default constructor should set all those the variables to a unit value.
- We also need a proper constructor that takes all three arguments.
- For the sake of demonstration, we need a third constructor that takes only width and height. This constructor should set the depth as a unit value.
Along with these three constructors, we also need reader and writer methods for all three
variables. How can we do that in
Scala style?
Let me explain. We need three constructors.
- No argument constructor
- Two argument constructor
- All three argument constructor.
The method is simple. Define one of those as a primary constructor, and other two goes as an
auxiliary constructor. But which
one do you want to define as a primary constructor?
There is a simple rule of thumb. Make all argument constructor as a primary and define
others
as an auxiliary constructor. Why is that rule? I will explain that in a minute. But before
that,
let's look at the code.
The first line defines the class and the primary constructor. The primary constructor takes width, height and the depth of the box. That first line does a lot of things for us.
- It defines the class.
- It also defines three instance variables. Width, Height, and the Depth.
- It goes further and defines the reader and writer for all three variables.
- That same line also defines the three-argument constructor.
That's why we always make the all-argument constructor as primary. If you make the no-argument
constructor as primary, you
won't get item 2 and 3 from above list. Rest of the code is simple.
We also define two auxiliary contractors. The auxiliary constructor name is always this.
So, both are named as this. The first constructor takes no arguments and the second
constructor
takes two arguments. There is one more rule for the auxiliary constructor. The auxiliary
constructor
must start with a call to a previously defined auxiliary constructor or the primary
constructor.
In our example, both auxiliary constructors are calling the primary constructor. The first one
is
setting all values to 1 whereas the second one is setting the depth as 1.
The last line is to display all the three values. I kept it there for testing my code. Now
you
can instantiate the Box class with no arguments, two arguments or three arguments.
Great. That's all about Scala constructors. In the next session, I will talk about some other
Scala Object Oriented concepts.
Keep Learning and Keep growing.