This means that Option [Nothing] is a subtype of the [Int] option (due to covariance), right?
Right. Option[Nothing] is Option[Int] .
But with B>: A, we said that B must be a supertype ?! So how can we get int back?
It should not be a supertype. This requires A as a lower bound. This means that you can pass Int to getOrElse if A is Int .
But this does not mean that you cannot pass instances of the subclass. For instance:
class A class B extends A class C extends B scala> Option(new B) res196: Option[B] = Some( B@661f82ac ) scala> res196.getOrElse(new C) res197: B = B@661f82ac scala> res196.getOrElse(new A) res198: A = B@661f82ac scala> res196.getOrElse("...") res199: Object = B@661f82ac
I can pass an instance of C , because C can be added to B I can also pass a type above the inheritance tree, and getOrElse will return that type. If I pass in a type that has nothing to do with the type contained in Option , then the type with the smallest upper bound will be inferred. In the above case, this is Any .
So why is there a lower bound at all? Why not:
def getOrElse[B <: A](default: => B): B
This will not work, because getOrElse must either return A , which is contained in Option , or, by default, B But if we return A and A not B , so the type binding is not valid. Maybe if getOrElse returned A :
def getOrElse[B <: A](default: => B): A
This will work (if it were really defined that way), but you would be limited by type constraints. Therefore, in the above example, you can only pass B or C to getOrElse on Option[B] . In any case, this is not the case as in the standard library.
The getOrElse standard library allows you to pass anything to it. Say you have Option[A] . If we pass a subtype A , it will be added to A If we pass A , this is obviously normal. And if we pass some other type, then the compiler displays the smallest upper bound between them. In all cases, a correspondence of type B >: A is satisfied B >: A
Because getOrElse allows you to transfer something, many find it very difficult. For example, you could:
val number = "blah" // ... lots of code val result = Option(1).getOrElse(number)
And it will compile. We will only have Option[Any] , which is likely to throw an error somewhere else along the line.