This article hopes to demonstrate that even if the use of Scala is restricted to/ bounded by the OO paradigm, it is still WIN packed.I’ll try too highlight how terse Scala syntax can be, (both compared to Java and in its’ own right), by iteratively creating a simple (aka shortcut) domain object in Scala. From this SDO, it’s worth decomposing what is going on under the covers, seeing what the compiler adds for free, though a direct comparison to the equivalent SDO in Java is left to the reader.
So, first off, let’s create our initial SDO.
..and there we go, that’s it. done. We now have a fully fledged Scala class. Though this simple class won’t set the Earth alight, there are a couple of intersting things to note:
- the class employs the typical Occams’ razor approach to syntax seen in Scalas’ design, with no need to include the (surplus) curly braces after the class declaration, (as would be the case in Java)
- we can get a new instance of this class, (in the REPL [the interactive Scala shell – available via typing scala in a shell session]), as follows:
Declaring a new instance via the REPL will assign this class to a synthetic* instance (which is able to be referenced as whateverVariableIsNamedOnConsoleOutputBeforeTheColon [typically res0 in a new REPL instance]).
* synthetic refering to an instance generated automatically by the compiler and not hand written by the developer.
NOTE: Any classes created in an external editor can be pulled into a REPL session using the command ‘:load ScalaClassName.scala‘ whilst in the same directory as the source file during the REPL session. Also, this is pulling in the source class, so doesn’t require pre-compilation.
Next let’s add some field members to the class.
class MySDO(val name:String, var age:Int)
If we compile this class, we should see an equivalent named .class file appear in the same directory. Let’s investigate what’s in this class file by running javap against it. So from a shell/cmd line:
javap -private MySDO
By inspecting all the private members of the class we can see a few things have happened:
– the age parameter has been created as private variable, and is a primitive type
– the name parameter has been created as a private final variable
– the defined constructor has been created
– both age and name appear as no-param methods in the class, and return int and String types respectively
– age also has a weird looking method created called age_$eq which takes a primitive type of int as an argument
So how does this map to the source code ? and what can we can we interpret by this ?
As mentioned earlier there are no curly braces after the class declaration, (understandably as there’s no body to the class, so nothing that requires ‘delimiting’).
What is going on in the constructor definition ?
val name:String – in POE (plain old English ;-), translates to: there is a value of type String called name. In Scala there are two variable types, namely, values and variable (aka val and var). Using val or var is how to create a named reference to an object, which needs to be initialized when defined. The val type creates an immutable reference (i.e. one that cannot be changed after initialisation), whereas a var is a reassignable variable.
After the var/val ‘type’ of the reference, we see the field name, and finally the colon delimiter, before the object type. The arrangement of reference name before it’s type is probably one of the more novel syntactic differences in Scala for Java developer. The semantics involved are that Scala is upfront about treating references (and hence names of variables), as paramount, with the type being value added (and sometimes peripheral) information. This has the side effect of also neatly aligning reference names in the source code, regardless of the length of the type/class name.
In terms of the types used in the MySDO constructor, the String type is identical to the java.lang.String type, and this is reflected in the javap output. However, introspecting into the class shows the Int type in the original Scala constructor has become an int primitve in the generated class file. The salient (and fundamental) point here is that everything in Scala is an Object. Whether all fields actually appear as Objects in the compiled class format is a moot point, but everything in the Scala source is an Object. In itself this is a pretty [freakin’] sweet feature, and makes Scala a ‘purer’ Object language that many other languages that support primitive types. It also removes some ‘noise’ and thinking from the source file, and leaves the optimisation/mapping of wrapper Objects to their equivalent compiled types in the hands of a greater power… the compiler. There are also other side effect from this design, which will become apparent shortly.
Given that we have a val type in our constructor explains why the generated class file has a final field for that field. All the declared fields are private but are exposed for read access by the compiler via generated public methods that are exposed using the given variable names. Updating the value assigned to the var field (i.e. age) is as simple as:
mySDOInstance.age = 2 // Some new value
As a final taster into the basics of OO support in Scala, let’s add some default values into the constructor..
class MySDO(val name:String = "AAA", var age:Int = 999)
Creating an instance of this in the REPL (as
var t1 = new MySDO), and then printing out the name variable assigned to this instance, shows it has been initialised with the default value of “AAA”. This demonstrates Scalas’ support for default values for params. We can also see the support for named params in use here, by creating another instance of the class, and overriding a default constructor value:
var t2 = new MySDO(age = 3)
Upon printing out the age value from t2 (
println(t2 age)), we see that it is now ‘3’ instead of the default value of ‘999’.
Finally, let’s have a peek at one more, seeminly innocuous, keyword in Scala which adds enough syntactic sugar to our SDO to make it super sweet. That word is ‘case’.
case class MySDO(val name:String = "AAA", var age:Int = 999)
One of the most notable additions to a ‘case class’ is the generation of a sensible default, value based, == operation. Having a value based ‘==’ operation is another implication of having pure Object types in the language, and is another point of departure to Scala from Java. As all variables in Scala are Objects, == returns value based results for all types. In Java, == performs value based comparison for primitives only, and reference based comparison for Objects. To perform reference based comparison in Scala, the eq operation is available.
Also, case classes provide default factory implementations for the marked object, meaning that we can now drop the ‘new’ keyword to instantiate a new instance of our SDO, e.g.
var t1 = MySDO()
The final point worthy of mention at this juncture, is that case classes add ‘sensible defaults’ for hashCode and toString implementations. Hence calling println(t1) gives much more readable output than was available previously.
Later we’ll use case classes to perform pattern matching, which is one of (if not *the*) most powerful features of the Scala language.
For now, this has been a quick coverage of some of the features of the Scala language for Object based programming, and has shown enough language features to provide syntactic sugar to save time, save your keyboard and your fingers !