Scala Quick Notes :: Part - 5
Bhaskar S | 01/31/2015 |
Overview
In this part of the series, we will continue to look at the Object-Oriented capabilities of Scala such as Traits and Operator Overloading.
Hands-on With Scala - V
The following is the Scala program named Sample16.scala:
Executing the program Sample16.scala results in the output:
My name is Alice of 30 and resident of NY My name is Bob of 45, a resident of NY and an Electrician & Plumber I am an electrician I am a plumber
The following section explains some of the aspects of the Scala program Sample16.scala:
A Scala trait definition looks similar to a Scala class definition, except for the use of the keyword trait
Ex: trait Person { ... }
Think of a Scala trait as similar to a Java interface except that it can define both field(s) and/or method(s) [Java 8 interfaces allow concrete method implementations - default methods]
In a class inheritance, a sub-class can only inherit from one base class. With traits, a class can inherit (or mix-in) one or more traits
A Scala class can mix-in multiple traits with the condition that the first class or trait must be inherited using the keyword extends and the remaining traits must be mix-in using the keyword with
Ex: class EPPro(val n: String, val a: Int) extends Person with Electrician with Plumber { ... }
A Scala trait can define a field with a value (concrete field) or a field with no value (abstract field).
Abstract fields must be initialized in the class that mix-in traits with abstract fields.
An abstract field defined in a trait using the keyword val must use the keyword override in the class during initialization, while an abstract field defined using the keyword var does not
Ex: class NoPro(val n: String, val a: Int) extends Person { override val name = n; var age = a }
An abstract method defined in a trait must always use the keyword override in the class to define the method implementation
The following is the Scala program named Sample17.scala:
Executing the program Sample17.scala results in the output:
This is from SimpleLogger [02/01/2015] This is from DecoratedOneSimpleLogger [19:58:10] This is from DecoratedTwoSimpleLogger [02/01/2015] [19:58:10] This is from DecoratedThreeSimpleLogger
The following section explains some of the aspects of the Scala program Sample17.scala:
To restrict a Scala trait to mix-in with only class(es) that implement a specific parent class, use the format: trait NAME extends PARENT-CLASS { ... }.
In our example, the traits DatedLogger or TimedLogger will mix-in with only class(es) that inherit from the Logger class
One of the interesting features of Scala traits is to provide stackable modifications to class(es). In other words, a Scala trait allows us to change the behavior of a method in a Scala class. By mixing-in a bunch of traits with a class, one can stack those modifications on top of each other.
In our example, the traits DatedLogger and TimedLogger represent modifications since they change the behavior of the method log of the underlying SimpleLogger class.
Interesting thing to note is that both traits, DatedLogger and TimedLogger invoke the method log via the parent super (Logger) which is an abstract class. The call to a method via super in a trait is dynamically bound when the trait is mixed-in with a class (SimpleLogger) that provides a concrete implementation of the invoked method. In the trait the method must be defined with the keywords abstract override
The following is the Scala program named Sample18.scala:
Executing the program Sample18.scala results in the output:
f1 = 1/2 f2 = 2/3 f1 + f2 = 7/6 f1 - f2 = -1/6 f1 * f2 = 2/6
The following section explains one of the aspects of the Scala program Sample18.scala:
In Scala, operators are actually just another syntax for ordinary method calls. In other words, the expression o1 + o2 is in actuality the same as (o1).+(o2).
In our example for the Fraction class, we have defined three operator methods - one for addition (+), one for subtraction (-) and one for multiplication (*).
References