I've got a trait that looks like this (some further information can be found at this related question by myself although I don't think, it's needed for this question)
trait Extractor[-A,+B] {
def extract(d:A):B
//lots of other things
}
To use this in an existing java framework I would like this Extractor
to either have a function that returns a Comparator[B]
(being java.util.Comparator) or even better extend Comparator[A]
. Now that poses a problem because Comparator
s type parameter is ought to be invariant, while A
is contravariant and B
is covariant.
So I get errors like this:
scala> import java.util.Comparator
import java.util.Comparator
scala> trait Extractor[-A,+B] extends Comparator[A]
<console>:6: error: contravariant type A occurs in invariant position in type [-A,+B]java.lang.Object with java.util.Comparator[A] of trait Extractor
trait Extractor[-A,+B] extends Comparator[A]
^
scala> trait Extractor[-A, +B] {
| def comp:Comparator[B]
| }
<console>:7: error: covariant type B occurs in invariant position in type => java.util.Comparator[B] of method comp
def comp:Comparator[B]
^
Do you see any way out of this or is this just one of those cases where "using java generics in scala hurts"?
With help of type-bounds it's possible to do the following:
scala> trait Extractor[-A, +B] {
| def comp:Comparator[_ <: B]
| }
defined trait Extractor
You can make Extractor[A,B]
extend Comparator[A]
by using the @uncheckedVariance
annotation.
scala> import scala.annotation.unchecked.uncheckedVariance
import scala.annotation.unchecked.uncheckedVariance
scala> trait Extractor[-A,+B] extends java.util.Comparator[A @uncheckedVariance]
defined trait Extractor
@uncheckedVariance
is safe here because Comparator
could have been defined as Comparator[-T]
. There was a discussion around making Ordering
covariant for Scala 2.8 using this annotation.
Edit See this question for more about @uncheckedVariance
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With