Reputation: 15529
I am trying to define a method with the following signature:
def parse[T <: MyClass](statement: String): Try[List[T]] = {
My class is an abstract class:
sealed abstract class MyClass { }
case class MyClassChild(v: Int) extends MyClass
my parse
method returns a Success(List[MyClassChild])
But the compiler complains with the following error:
Error:(124, 19) type mismatch;
found : scala.util.Try[List[parser.MyClass]]
required: scala.util.Try[List[T]]
Why doesn't scala.util.Try[List[parser.MyClass]]
conform to scala.util.Try[List[T]]
, since T <: MyClass
?
Thank you
Upvotes: 0
Views: 199
Reputation: 22374
T
should be >: MyClass
and Try[List[T]] >: Try[List[MyClass]]
(List and also Try is covariant, so it will work) to confirm return type - because your function can't return bigger type than declared (see Liskov substitution principle ):
scala> trait A { type MT; def aaa[T <: MT]: List[T] = null.asInstanceOf[List[MT]] }
<console>:7: error: type mismatch;
found : List[A.this.MT]
required: List[T]
scala> trait A { type MT; def aaa[T >: MT]: List[T] = null.asInstanceOf[List[MT]] }
defined trait A
If you want T <: MyClass
- you should change return type to Try[List[MyClass]]
:
scala> trait A { type MT; def aaa[T <: MT]: List[MT] = null.asInstanceOf[List[MT]] }
defined trait A
In other words, you can't "shrink" MyClass
to T
even theoretically because it's bigger by T <: MyClass
definition. MyClass.asInstanceOf[T]
will give you type cast error with probability > 0, it's like Any.asInstanceOf[String]
.
Upvotes: 1