Scala Quick Notes :: Part - 3
Bhaskar S | 01/18/2015 |
Overview
In this part of the series, we will look at the Object-Oriented capabilities of Scala such as defining and using a class, as well as defining and using a companion object.
Hands-on With Scala - III
The following is the Scala program named Sample08.scala:
Executing the program Sample08.scala results in the output:
c1 = EContact1-[Alice, alice@earth.com, 10002] c2 = EContact1-[Bob, bob@mars.com, 10003] c3 = EContact2-[Charlie, charlie@space.com, 10004] c4 = EContact3-[Eve, eve@mars.com, 10005] c5 = EContact3-[Frank, frank@northpole.com, 10001]
The following section explains some of the aspects of the Scala program Sample08.scala:
A Scala source file can contain many class definitions (unlike Java) with various names (different from the source file name)
Use the template class NAME { ACCESS val|var FIELD-1 [= INIT-1]; ACCESS val|var FIELD-2 [= INIT-2]; ACCESS val|var FIELD-n [= INIT-n]; def METHOD-1(PARAMS-1) = { ...}; def METHOD-2(PARAMS-2) = { ... }; def METHOD-n(PARAMS-n) = { ... } } to define a Scala class
Ex: class EContact1 { ... }
This form of Scala class definition is similar to the one from Java.
Use the method name this followed by the desired parameter list to define an auxiliary constructor.
Ex: def this(n: String, e: String, z: String) = { ... }
Use the keyword override in a method definition if we want to redefine a pre-defined method like toString for a Scala class.
All Scala classes extend from the parent Scala type Any. The method toString is from this class.
Ex: override def toString() = { ... }
The default field or method access level in a Scala class is public.
Ex: class EContact2 { ... }
Use the template class NAME (ACCESS val|var PARAM-1, ACCESS val|var PARAM-2, ACCESS val|var PARAM-n) { ACCESS val|var FIELD-1 [= INIT-1]; ACCESS val|var FIELD-2 [= INIT-2]; ACCESS val|var FIELD-n [= INIT-n]; def METHOD-1(PARAMS-1) = { ...}; def METHOD-2(PARAMS-2) = { ... }; def METHOD-n(PARAMS-n) = { ... } } to define a Scala class with a primary constructor. The parameter list for the primary constructor are defined right after the class name.
Ex: class EContact3(val name: String, val email: String, val zip: String = "10001") { ... }
If one does not define a primary constructor explicitly, then the implicit primary constructor is this().
The parameter list specified in the primary constructor are converted to individual fields of the class by the Scala compiler. Hence the reason we are able to access the fields - name, email, and zip in to toString() method in the class EContact3
The following is the Scala program named Sample09.scala:
Executing the program Sample09.scala results in the output:
[1] a1 = Account-[1000, Alice, 1050.0] a1.name = Alice a1.balance = 1050.00 [2] a1 = Account-[1000, Alice, 100.0] a2 = Account-[1001, Bob, 950.0] a2.name = Bob
The following section explains some of the aspects of the Scala program Sample09.scala:
When Scala sees a var field in the primary constructor parameter list, it generates both the accessor (getter) and the mutator (setter) methods.
In the Scala program Sample09.scala, the access of the field a1.balance is actually an invocation of the method a1.balance().
Similarly, the update of the field a1.balance = 100.0 is actually an invocation of the method a1.balance_$eq()
When Scala sees a val field in the primary constructor parameter list, it only generates the accessor method
When Scala sees a field with neither a var nor a val in the primary constructor parameter list, it does not generate either the accessor or the mutator methods.
This is why trying to access the field a1.no generates a compiler error
Adding the keyword private before a var triggers the Scala compiler to not generate either the accessor or the mutator methods.
This is why trying to access the field a2.balance generates a compiler error
The following is the Scala program named Sample10.scala:
Executing the program Sample10.scala results in the output:
Value of PI = 3.14 Area of circle with radius 10 m = 314.16 sqm fibonacci(0) = 0 fibonacci(1) = 1 fibonacci(2) = 1 fibonacci(5) = 5 fibonacci(10) = 55 factorial(0) = 1 factorial(1) = 1 factorial(2) = 2 factorial(5) = 120 factorial(10) = 3628800
The following section explains some of the aspects of the Scala program Sample10.scala:
Scala does not have the static keyword unlike Java. Instead use an object to emulate the behavior.
To create a single instance of an entity (singleton), define that entity using the object keyword instead of the class keyword
Ex: object MyMathFun { ... }
One does *NOT* use the new keyword to create an instance of an object - we directly use the object name as it is a singleton
Use the template ObjectName.FieldName to access a field defined in an Object
Ex: MyMathFun.PI
Use the template ObjectName.MethodName(params) to to invoke a method defined in an Object
Ex: MyMathFun.factorial(5)
The following is the Scala program named Sample11.scala:
Executing the program Sample11.scala results in the output:
f1 = Font1-[Arial] f2 = Font1-[Courier] f3 = Font2-[Sans]
The following section explains some of the aspects of the Scala program Sample11.scala:
When an object name matches a class name, the singleton object is called a companion object of the class
Ex: class Font1 (name: String) { ... } and object Font1 { ... }
To make the companion object of a class the factory of the class and prevent one from directly creating instances of the class, use the keyword private before the primary constructor parameter list of the class
Ex: class Font2 private (name: String) { ... }
References