Previously I had written about Companion classes in Scala and there in I had mentioned one of its uses i.e defining the apply method to support object literals. In this post I am continuing from where I had previously left and pick two such Companion classes in Scala API called the Option class and the Either class and their associated case classes.

In this post I would like to cover:

What are case classes?

From the Official Scala Doc:

Scala supports the notion of case classes. Case classes are regular classes which export their constructor parameters and which provide a recursive decomposition mechanism via pattern matching.

Examples of the case classes include scala.Some, scala.util.Left, scala.util.Right. And the application of case classes can be read in the below topics.

What is Option class?

From the Scala API, Option class:

Represents optional values. Instances of Option are either an instance of scala.Some or the object None.

Prior to Java 8, there is no support for creating objects which either hold some value or dont hold any value. This support has been provided by external APIs like Guava and others. In Java 8 there is a new class added called Optional ( I would write about this sometime in future).

There are 2 variants of Option namely Some and None. The former represents presence of a value and stores the value within it and the latter represents the absence of value. Lets have a look at an example:

//Uses of Option class
object OptionDemo {
  def main(args: Array[String]) {   
    val result1 = loadData(true)
    val result2 = loadData(false)
    println(result1.getClass())//Prints class scala.Some
    println(result2.getClass())//Prints class scala.None$

    //getOrElse- either returns the value present or 
    //returns the value after evaluating the parameter.
    println(result1.getOrElse("Error!"))
    println(result2.getOrElse("Error!"))
    
  }

  def loadData(condition: Boolean): Option[String] =
    if (condition) {
      Some("Data found!")
    } else {
      None
    }

}

In the above simple example an instance of Some or singleton None is returned by the loadData based on some condition and then make use of the return values to print out the their types as well as their contents using the getOrElse method. Lets see another way to make use of the return values from the loadData method. In the below example we make use of the advanced pattern matching mechanism to extract the contents of the object. This is possible because the classes Some and None are case classes.

object OptionDemo {
  def main(args: Array[String]) {   
    val result1 = loadData(true)
    val result2 = loadData(false)
    
    //Prints: found details:Data for employee 1234
    matcher(result1)
    //Prints: No data found
    matcher(result2)
  }
  
  //Using pattern matching to decompose the parameter.
  def matcher(result: Option[String]){
    result match{
      case Some(msg) => println("found details:" + msg)
      case None      => println("No data found")
    }
  }

  def loadData(condition: Boolean): Option[String] =
    if (condition) {
      Some("Data for employee 1234")
    } else {
      None
    }

}

What is Either class?

From the Scala API, Either class:

Represents a value of one of two possible types (a disjoint union.) Instances of Either are either an instance of scala.util.Left or scala.util.Right.

And just after the it states the use of Either class:

A common use of Either is as an alternative to scala.Option for dealing with possible missing values. In this usage, scala.None is replaced with a scala.util.Left which can contain useful information. scala.util.Right takes the place of scala.Some. Convention dictates that Left is used for failure and Right is used for success.

In the below example we make use of Left class to populate the data is some operation is successful and make use of Right class to populate the exception message in case of failure. The success condition is when the passed number is even and the failure condition is when the passed number is odd.

object EitherDemo {
  def main(args: Array[String]) {
    val div1 = even(12)
    val div2 = even(11)
    matcher(div1)//Prints 12.0
    matcher(div2)//Prints "The number 11.0 is not even"
    
  }
  
  def matcher(matchElement:Either[String, Double]){
    matchElement match {
      case Left(msg) => println(msg)
      case Right(rem) => println(rem)
    }
  }

  def even(number:Double): Either[String, Double] =
    if (number % 2 == 0) {
      Right(number)
    } else {
      Left("The number "+ number +" is not even");
    }

}

In the above example Left and Right case classes have been used in pattern matching in the same way the classes Some and None were used in the first example.

This was in very brief about Option and Either classes in Scala and how case classes can be used for pattern matching.

 
About The Author

Mohamed Sanaulla

Leave a Reply