Search code examples
scalanullscala-option

getting a java.io.Serializable from Option[..] in Scala


(just started with Scala a few weeks ago, so bear with me)

Reading/trying out this little article here, ran into some surprises

http://danielwestheide.com/blog/2012/12/19/the-neophytes-guide-to-scala-part-5-the-option-type.html

After defining a case class User as described:

case class User(
  id: Int,
  firstName: String,
  lastName: String,
  age: Int,
  gender: Option[String])

object UserRepository {
  private val users = Map(1 -> User(1, "John", "Doe", 32, Some("male")),
                          2 -> User(2, "Johanna", "Doe", 30, None))
  def findById(id: Int): Option[User] = users.get(id)
  def findAll = users.values
}

, here are the gets I observe:

> scala> UserRepository.findById(1)
> res34: Option[User] = Some(User(1,John,Doe,32,Some(male)))
> 
> scala> UserRepository.findById(1).get
> res35: User = User(1,John,Doe,32,Some(male))
> 
> scala> UserRepository.findById(1).getOrElse("N/A")
> res36: java.io.Serializable = User(1,John,Doe,32,Some(male))
>
> scala> UserRepository.findById(3).getOrElse("N/A")
> res37: java.io.Serializable = N/A

The first two are what I expected, but the second two aren't; both the case of existing and non-existing Users. Why java.io.Serializable, all of the sudden?


Solution

  • To understand this you have to understand what is getOrElse

    final def getOrElse[B >: A](default: => B): B
    

    getOrElse is defined on Option. Option can be Some(value) or None.

    getOrElse returns default when option is none

    val map = Map(1 -> 2)

    map.get(1) returns option

    scala> Some(1).getOrElse(2)
    res3: Int = 1
    
    scala> Some(1).getOrElse("Hello")
    res4: Any = 1
    
    
    scala> case class User(name: String)
    defined class User
    
    scala> (None: Option[User]).getOrElse("a")
    res12: java.io.Serializable = a
    
    scala> (None: Option[User]).getOrElse(1)
    res7: Any = 1
    

    Coming to the point

    Some(a).getOrElse(b)

    if a and b are of same type then resultant type will be a type or b type

    if a and b are not of same type then resultant type will be nearest common super type which is java.io.Serializable in your case.

    Note that

    1) nearest common super type for User and String is Serializable

    2) nearest common super type for User and Int is Any