Showing posts with label apply. Show all posts
Showing posts with label apply. Show all posts

Monday, 28 May 2018

Object in Scala

In Scala, objects are a singleton. Scala doesn’t have static class members (variables or methods). Instead, it has singleton objects.

Simple example of object:

object Person

As an object is a singleton, it does not have constructor  parameters.

Ex –

object Person(age: Int){} // Error
object Person(){} // Error
object Person{} // Success

object Person{
  val age : Int = 10
  var name : String = "Prashant"
  def bmi(height:Int, weight:Int) = weight/height
}

Above object has two parameters and one method. We can relate these parameters as static parameters in a java.

To call a method from the object, we don't need instance as doesn't require new keyword, we can call  method like "Person.bmi".

An object with the same class name in one file called companion object.
We can define apply(), unapply() and update() methods in an Object.

apply method is a special method in Scala. when we do obj(parameter), Scala calls obj.apply(parameter)

object Person {
   def apply() = {
    println("zero argument apply function")
  }

  def apply(a: Int, b: String) = {
    println("Two argument apply function")
  }

  def update(a: Int) = {
    println("Update : a : [" + a + "]")
  }

  def update(a: Int, b: Int, c: String) = {
    println("Update : a : [" + a + "] : [b] : [" + b + "] : [c] : [" + c + "]")
  }

}


object Client extends App { 
  Person
  Person()
  Person(1, "Hi..")
  Person() = 2
  Person(4, 5) = "Hello.."
}

Output :
zero argument apply function
Two argument apply function
Update : a : [2]
Update : a : [4] : [b] : [5] : [c] : [Hello..]

We can use apply method in a companion object as a Factory/builder.

Ex:
abstract class DatabaseDriver {
  // some database stuff
}

object DatabaseDriver {
  def apply(config: Configuration) = config.dbType match {
    case "MYSQL" => new MySqlDriver()
    case "PSQL" => new PostgresDriver()
    case _ => new GenericDriver()
  }
}

val mydatabase = DatabaseDriver(dbConfig)

internally it will call

val mydatabase = DatabaseDriver.apply(dbConfig)

We can override apply method several times, to get the different behavior.

Wednesday, 20 December 2017

Scala apply and unapply



apply and unapply are the special methods in Scala. The apply method works like a constructor. Unapply uses to extract the object. The unapply method used for pattern matching.

In another word, we also call them extractor.

package scala.practice

/**  * Created by prashant on 19/12/17.  */object Foo {

  def apply(maths:Int, science:Int): Int ={
      println("I am from apply method")
      maths+science
  }

  def unapply(maths: Int): Option[String] ={
    println("I am from unapply method")
    if(maths> 40) Some("Passed") else None
  }

  def main(args: Array[String]): Unit = {
    val fooObj = Foo(10,10); //I am in apply method
//   val Foo(res) = fooObj;

//    println("Res: "+ res)  // This will cause matcherror.
    fooObj match {
      case Foo(res) => println("Test Passed") //This line will call a unapply method.

      case _ => println("Test failed")
    }
  }

}


apply and unapply need not be opposite to each other.

apply is simple, Whenever we call Object(a,b,c) it internally calls Object.apply(a,b,c). The apply method can have zero or more parameter.

The unapply method is a bit complicated!

    val fooObj = Foo(10,10); //I am in apply method   //Line 1 

    //val Foo(res) = fooObj;   //Line 2 

in line number 2, Scala compiler executing unapply method.  It internally calls,
   val res =Foo.unapply(fooObj).get

Unapply method return type could be boolean or Optional.

The unapply method CAN NOT HAVE MORE THAN ONE PARAMETER, IT SHOULD ALWAYS HAVE SINGLE PARAMETER.

The reason behind that,

 fooObj match {
      case Foo(res) => println("Test Passed") //This line will call a unapply method.      case _ => println("Test failed")
    }


In above code, fooObj is an input parameter for an unapply method, We can not match more than one parameter so unapply never have multiple parameters. If there is no match, It will throw  "scala.MatchError"  error.

In above code as unapply method return None, which matches with "case_ =>", so it does not throw any error.

//    val Foo(res) = fooObj;   //Line 2 

In above code result "None" does not match So It throws an error.

Summary: apply method used to CONSTRUCT the object and unapply used to extract the object.