Sunday, August 11, 2013

Chapter 2: Scala Features for Java Developer

In this post, I am going to attempt to visit the scala features that help write succinct and intuitive code. As a Java developer I appreciate the productivity they bring.

1. Concise Class definition
2. Type Inference
3. Defining mutable/immutable objects by declaration
4. Static Typing
5. Function definitions
6. Traits

1. Concise Class definition

I always thought that my beans were too verbose due to the getters and setters.
Let us define a class Person, with attributes id and name in scala.

All java programmers know how many lines of code we will write just to define and access these values.
The same code in scala is

class Person (var id: String, var name:String, var citizen:String);

Notice that there are
    no getters and setters (since the attributes are defined var, they are implicitly mutable.
    The body is completely optional for a class.

2. Type inference

Now let us instantiate a new Person, assign a new id to and print it.

1. var p = new Person("20", "Mike", "EURO")
2. p.id = 20;
3. println (p.id)

We did not have to specify the type of the variable p, scala compiler can infer its type from its assignment.

3. Making objects mutable and/or immutable.

Let us say we wanted to make the Person class immutable, in Java we would have to take many actions
remove setters, make the attributes/fields final etc., a favorite interview question.

In scala, this needs just the declaration change from var to val, Person (val id: String, val name:String)
We replace var in the class definition with val. var is a variable, val is a value hence immutable.

Now the statement at line 2 above, will not compile. There is not setter available for this class.

To see the code generated by scala and java, go to the bin directory of the code where the class files are generated, now if you do

scalap Person, you see
class Person extends scala.AnyRef {
  val id : scala.Predef.String = { /* compiled code */ }
  var name : scala.Predef.String = { /* compiled code */ }
  def this(id : scala.Predef.String, name : scala.Predef.String) = { /* compiled
 code */ }
}

To see the java code, just do
javap Person.class and you will see

public class org.manu.blog.Person {
  public java.lang.String id();
  public java.lang.String name();
  public void name_$eq(java.lang.String);
  public org.manu.blog.Person(java.lang.String, java.lang.String);
}

As you can see, name has a getter and a setter, while id has just the getter defined.
Later we will see what $eq means in java code and what Predef means in the scala code.

4. Static Typing

Let us define another class Manager, class Manager (val reports: Int)

Now let us try the code below

  1.     var p = new Person ("10", "Larry")
  2.      p.id = "20;"
  3.      println (p.id);
  4.      p = new Manager(3);
The compiler throws error, since the type of p (Person) does not match with the type Manager.

Type inference does not make scala dynamically typed language. All the refactoring tools still work.

5. Function Definitions

Functions are the foundation of functional programming, to explore the power of functional programming, let us define some functions. I have person data consisting of US citizens and European Citizens. For a US citizen I will validate SSN, for a European person, I need to validate European passports
I define a trait called validatePerson as follows


trait ValidatePersons {
  def validateSsn(ssn: String): Boolean = { println("Will validate SSN"); true }
  def FBIFingerPrints(ssn: String): Boolean = { println("Will validate FBI Fingerprints"); true }
  def validateEuroPid(eid: String): Boolean = { println("Will validate Euro PID"); false }
}

We will see the trait in detail later, for now, trait is an interface with implemented methods.
How does scala define the functions, starting with the word def.
The important thing to note is it return Boolean, and not boolean.
This is because everything is an object in scala, there are no primitives and operators are methods.

6. Traits

This is another flexible feature. Traits are more like interfaces with some implemented methods, In java the interfaces are married at class definition.Once implemented for a class it is always there for all objects.
In scala it is different, it is attached to the behavior when a variable is defined.

Let us see how it works.
  1.       var p = new Person("20", "Mike", "EURO") with ValidatePersons;
  2.       p  = new Person("10", "Larry", "USA") ;
  3.       p.validateSsn(p.id)
 This code does not compile. This is because the variable p  at line 2 is not defined with ValidatePersons and so it does not have access to the validateSsn method. 
Now change it to the following and it will start working. I like the fact that one can mixin a trait any time.
It is not married to the class.
  1.       var p = new Person("20", "Mike", "EURO") with ValidatePersons;  
  2.       p  = new Person("10", "Larry", "USA") with ValidatePersons;
  3.       p.validateSsn(p.id)
Right now, my functions are not very different from the methods in terms of the usage. In the next post I will explore the power of passing of the function. 

No comments:

Post a Comment