Understand how to use apply and unapply

scala

Solution

Firstly, `apply` and `unapply` are not necessarily opposites of each other. Indeed, if you define one on a class/object, you don't have to define the other.

apply

`apply` is probably the easier to explain. Essentially, when you treat your object like a function, apply is the method that is called, so, Scala turns:

`obj(a, b, c)` to `obj.apply(a, b, c)`.

unapply

`unapply` is a bit more complicated. It is used in Scala's pattern matching mechanism and its most common use I've seen is in Extractor Objects.

For example, here's a toy extractor object:

object Foo {
  def unapply(x : Int) : Option[String] = 
    if(x == 0) Some("Hello, World") else None
}

So now, if you use this is in a pattern match like so:

myInt match {
    case Foo(str) => println(str)
}

Let's suppose `myInt = 0`. Then what happens? In this case `Foo.unapply(0)` gets called, and as you can see, will return `Some("Hello, World")`. The contents of the `Option` will get assigned to `str` so in the end, the above pattern match will print out "Hello, world".

But what if `myInt = 1`? Then `Foo.unapply(1)` returns `None` so the corresponding expression for that pattern does not get called.

In the case of assignments, like `val Foo(str) = x` this is syntactic sugar for:

val str : String = Foo.unapply(x) match {
  case Some(s) => s
  case None    => throw new scala.MatchError(x)
}

Problem

I'm trying to get a better understanding of the correct usage of `apply` and `unapply` methods. Considering an object that we want to serialize and deserialize, is this a correct usage (i.e. the Scala way) of using `apply` and `unapply`? ``` case class Foo object Foo { apply(json: JValue): Foo = json.extract[Foo] unapply(f: Foo): JValue = //process to json } ```

Original source

Related problems