Reputation: 9803
The problem:
Looking at this question about migrating the Java signature
public <A extends Comparable<? super A>> void sort(List<A> list) { }
to Scala, there doesn't seem to be a way to avoid a
illegal cyclic reference involving type T
error if you do a literal translation like this.
def compilerFailure[T <: Comparable[_ >: T]](a: Array[T]): T = { }
The workaround seems to be to do this instead
def workaround[A <: Comparable[U], U >: A](list: List[A]) { }
which if you round trip from byte code back to Java, you get this (which looses the super
part)
public <T extends Comparable<U>, U> void scalaToJava(List<U> a) { }
My questions:
Is the scalaToJava
version equivalent to the following?
public <T extends Comparable<?>> void sort(List<T> a) {
I figured when U
is unbounded, it might as well be ?
or Object
no? Then if that's the case, is the Scala workaround
version equivalent to
def sort[A <: Comparable[_]](list: List[A]) { }
They all seem to compile for my use case (which is about putting different sub-types in a collection and being able to sort them). NB. I'm curious about the mechanics and what causes the cyclic reference error and realize that Scala offers better alternatives in terms of covariance etc (ie Ordering
).
Upvotes: 4
Views: 365
Reputation: 5426
public <T extends Comparable<?>> void sort(List<T> a)
is too general because then you could for instance pass in a List<A> extends Comparable<Int>
where the compare function would not be applicable to values of type List<A>
.
You were on the right track with your workaround but made a little mistake. It should be:
def workaround[A <: Comparable[A], U >: A](list: List[U]) { }
But notice that this is not the way this sort of situation is usually solved in Scala:
See scala.math.Ordering
.
Upvotes: 4