In Previous chapter we learned about SCALA PATTERN MATCHING and today lets check out SCALA CLASS.
A Scala Class is a collection of variables , methods ,objects etc. You would have read another definition that class is the blueprint of an object, this statement would not make sense now. Lets look at some examples and then we will come back to the definition.
Syntax of a simple class:
scala> class student {} defined class student
In the above syntax
class is the keyword
student is the class name
{ } contains the body of the class
The above class student can be defined but it actually doesn’t do anything. You can create an instance of this Scala class in similar way to other languages using the keyword new.
scala> var stu1 = new student stu1: student = student@7298c2d9 scala> var stu2 = new student stu2: student = student@4b4bc73d
Now stu1 and stu2 are instances of the Class also known as objects. These objects will have the same template as that of the class. If we create a class with a field and function all the objects created from that class will have a field and function. Hence this is why class is called blueprint/template of an object.
Lets add variables and functions in the class. Remember that, variable inside a class is called field and function inside a class is called method.
scala> class student { | var name = "Smith" | def printname ={ println( "The name is " + name)} | } defined class student
Note here that I did not have to specify the datatype of name field yet the compiler did not throw error. This is because of Type Inference in Scala. You can learn more about it here.
GETTER AND SETTER METHOD
Here name is a field and printname is a method. Also notice that i have used var for name field. If I now create a student object obj1, by default a getter and a setter method will be created for field “name”. Using getter you can get/print the value and using setter you can set a new value to name. Lets check this with an example below.
scala> val obj1 = new student obj1: student = student@10d5e2dc scala> print(obj1.name) Smith scala> val obj1 = new student obj1: student = student@40053c7a scala> print(obj1.name) // use the getter method to get the value of name and print it Smith scala> obj1.name = "Harry" // use setter method to set a new value to field name obj1.name: String = Harry scala> print(obj1.name) Harry
Now this means that if I would have used val for name field, only getter method would have got created. And yes that’s true, the compiler would have thrown the error [error: reassignment to val]. You can try this out yourself.
SCALA CLASS PRIVATE MEMBERS
The field name created in student class is by default PUBLIC, which means the members can be used outside the class. Which also means using getters and setters methods, we can access the fields once the object is created. So when we don’t define anything it looks like below
Public Var name [ the compiler creates getter and setter method for the object]
Publiv Val name [ the compiler creates getter method for the object]
So, if we want no getters and setters method to be created for the object we need to use PRIVATE keyword. Lets check the example below.
scala> class student { | private var name = "Smith" | name = "Perth" | def printname ={ println( "The name is " + name)} | } defined class student scala> val obj1 = new student obj1: student = student@359a2c96 scala> obj1.name <console>:26: error: variable name in class student cannot be accessed in student obj1.name ^ scala> obj1.printname The name is Perth
In the above example the field ‘name’ is Private. So when we create an object obj1 we can neither read the field nor can we assign it. So making the field private means we can only use it inside the class.
SCALA CONSTRUCTORS
There are 3 types of Scala Constructors
- Default Primary Constructor
- Auxiliary Constructor
Default Primary Constructor
When we create a Scala Class the compiler creates a constructor by default. In the below example a constructor is created which does not take an arguments this is called as Default Primary Constructor.
scala> class student { | var x = 5 | } defined class student scala> val obj1 = new student()
Now lets create a class which takes a parameter in this a Primary Constructor is created which takes one parameter .
scala> class student (var name :String) { | println(name) | } defined class student scala> val obj1 = new student("Smith") Smith obj1: student = student@496e0f9d
Few things to notice with the code above
1. Scala doesnt create a default constructor but rather creates primary constructor which takes a parameter.
2. You see that the paramter ‘name’ behaves like a field. We didn’t have to assign the input parameter to some field and then use the field but rather we could directly use parameter as field. This is because Scala creates a getter and setter method for the input parameter.
3. As we are using var for input parameter, both getters and setters are created. If we make it val only getters will be created . Similar to our discussions before if we want Scala not to create any getter or setter methods then we can make it PRIVATE.
4. When we do not specify anything ex:- class student(name:String) then by default it is Private Val.
5. As we have defined a Primary constructor the default constructor is not created.
Auxiliary Constructor
Even if a primary constructor is created you can still create a Default Constructor and also create few other constructors. These are known as Auxiliary Constructor.
Lets understand this with an example. Create a class with 3 Constructors, which takes numbers multiplies and prints them.
1. class mul() – Takes no arguments
2. class mul(x:Int , y:Int) – Takes 2 arguments
3. class mul(x:Int , y:Int , z:Int) – Takes 3 arguments)
Now one of these is a Primary Constructor and remaining 2 are Auxiliary Constructor. Always choose the class with all parameters as the Primary constructor. The reason being, setters and getters needs to be created for all the parameters, if you choose one with no or less arguments the remaining parameters does not get initialized.
scala> class mul(x:Int , y:Int , z:Int) { | def this() = { this(1,1,1) } //if no args are passed | def this(x:Int , y:Int) = { this(x,y,1) } // when 2 args are passed | def printval = { println(x * y * z) } | } defined class mul scala> val obj1 = new mul(3,4,5) obj1: mul = mul@3abc4498 scala> obj1.printval 60 scala> val obj2 = new mul(3,4) obj2: mul = mul@653b49c4 scala> obj2.printval 12 scala> val obj3 = new mul() obj3: mul = mul@4e5c1817 scala> obj3.printval 1
Lets understand the code above
1. mul(x:Int , y:Int , z:Int) is the class and also the Primary Constructor. Here 3 instance variables are created along with getters and setters .
2. The 2 functions starting with ‘this’ are the Auxiliary Constructors and they should always be named ‘this’. The second rule which Auxiliary Constructors must obey is they must call some other Auxiliary Constructor or the Primary Constructor. In our case you can see that both the constructors are calling the Primary Constructor.
3. def this() is an Auxiliary Constructor with no argument and def this(x:Int , y:Int) is another Auxiliary Constructor which takes 2 arguments.
4. In line 8, 14, 20 you can see that i have instantiated objects by passing different arguments.
Why Not to use Auxiliary Constructor
We noticed above that every auxiliary constructor needs to call either an auxiliary or primary contractor. What it is trying to do is pass the missing parameters with some default arguments. And if this is what we plan to achieve then it can be easily done using DEFAULT ARGUMENTS. So instead of three constructors we can simply write the code as below.
class mul(x:Int = 1 , y:Int =1 , z:Int = 1){ def printval = { println(x * y * z) } }
In the next chapter we will learn about SCALA SINGLETON AND COMPANION OBJECT