Consider the below:
trait AA {
def children: List[AA]
}
trait BB {
def children: List[BB]
}
class CC extends AA, BB {
override def children: List[AA] & List[BB] = ???
}
When we override children
in CC
, the overridden method is merged entity of the top-level methods. And hence the return type List[AA] & List[BB]
makes sense.
What I don't understand is, how does the below compile?
class DD extends AA, BB {
override def children: List[AA & BB] = ???
}
List is co-variant, hence (here is the source for proof):
List[AA & BB] <: List[AA] & List[BB]
DD
can only compile if also List[AA] & List[BB] <: List[AA & BB]
. Is it true?
And if so, then isn't List[AA] & List[BB] =:= List[AA & BB]
. Please suggest
It appears to me that List[AA & BB] =:= List[AA] & List[BB]
. Consider this:
val xx: List[AA & BB] = ???
val yy: List[AA] & List[BB] = ???
val z1: List[AA] & List[BB] = xx
val z2: List[AA & BB] = yy
You write that for DD to compile, List[AA] & List[BB]
must be a subtype of List[AA & BB]
. I don't see why you think that, and you're in fact mistaken. Method return types are covariant, and hence it's the other way around: List[AA & BB]
must be a subtype of List[AA] & List[BB]
. And this is indeed the case, so the code is fine.