Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Scala generic array

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.

like image 225
halfwarp Avatar asked Jul 16 '26 16:07

halfwarp


2 Answers

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

like image 106
Kevin Wright Avatar answered Jul 19 '26 04:07

Kevin Wright


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
like image 34
Vasil Remeniuk Avatar answered Jul 19 '26 05:07

Vasil Remeniuk