Reputation: 368
I am looking at scala in action book and it has this code
sealed abstract class Maybe[+A] {
def isEmpty: Boolean
def get: A
def getOrElse[B >: A](default: B): B = {
if(isEmpty) default else get
}
}
final case class Just[A](value: A) extends Maybe[A] {
def isEmpty = false
def get = value
}
case object Nil extends Maybe[scala.Nothing] {
def isEmpty = true
def get = throw new NoSuchElementException("Nil.get")
}
If the signature of getOrElse is defined as def getOrElse(default: A): A = It doesnt compile.
The author states "The lower bound B >: A declares that the type parameter B is constrained to some super type of type A"
Yet I seem to be able to do this and it works
val j1 = Just(1)
val l1 = j1.getOrElse("fdsf") //l1 : Any = 1
Is String a super type of Int? What am i not understanding as to why this works? Its like its falling back to argument 1 being type A being of type Any (which it is) rather than type Int.
Upvotes: 2
Views: 393
Reputation: 61128
In Scala you cannot have covariant types in method parameters.
This is because allowing covariant types in method parameters breaks type safety.
In order to have a covariant type you must use a bounded type:
getOrElse[B >: A](default: B): B
This says find some type, B
, such that it is a superclass of A
and that becomes the method return type.
In your case A
is Int
and you pass in a String
. The only type B
which is a superclass of both Int
and String
is Any
.
In this case B
becomes Any
so the method returns Any
.
Upvotes: 3