Reputation: 1790
I'm trying to declare a method in an abstract class which receives an Array of generic type T. As such:
abstract class Circle[-T] extends Shape[T] {
def draw(points: Array[T]): Unit
}
The problem I'm getting is that Scala compiler complaints with:
contravariant type T occurs in invariant position in type Array[T] of value points
So, is there anyway to solve this besides the following?
def draw[U <: T](points: Array[U]): Unit
As a note, I also need to extend this class in Java.
Upvotes: 3
Views: 946
Reputation: 20627
Related to this question. You can either skip check for variance
scala> import scala.annotation.unchecked.uncheckedVariance
import scala.annotation.unchecked.uncheckedVariance
scala> abstract class Circle[-T] extends Shape[T @uncheckedVariance] {
| def draw(points: Array[_<:T]): Unit
| }
defined class Circle
or use a view bound
scala> abstract class Circle[T<%T] extends Shape[T]{
| def draw(points: Array[_<:T]): Unit
| }
defined class Circle
Upvotes: 3
Reputation: 49705
Scala's Array maps directly to Java arrays, and is invariant ([T]
instead of [+T]
)
Array is a tricky beast. It's about the only thing that gets reified on the JVM, and it's common knowledge that array variance is purposely broken so that methods like Arrays.sort() could be implemented.
You'd probably be better off using a "true" Java collection here.
To answer the more general question: Yes, if you want to use a parametrised invariant type in a method of a contra-variant class, you have to specify an upper bound in the signature for that method
Upvotes: 4