Общий массив Scala

Я пытаюсь объявить метод в абстрактном классе, который получает массив универсального типа T. Таким образом:

abstract class Circle[-T] extends Shape[T] {
   def draw(points: Array[T]): Unit
}

Проблема, которую я получаю, заключается в том, что компилятор Scala жалуется на:

контравариантный тип T встречается в инвариантной позиции в типе Array[T] значений точек

Итак, есть ли способ решить эту проблему, кроме следующего?

def draw[U <: T](points: Array[U]): Unit

В качестве примечания мне также нужно расширить этот класс в Java.


person halfwarp    schedule 15.10.2010    source источник


Ответы (2)


Массив Scala напрямую отображается в массивы Java и является инвариантным ([T] вместо [+T])

Массив — хитрый зверь. Это единственная вещь, которая конкретизируется в JVM, и общеизвестно, что дисперсия массива намеренно нарушена, чтобы можно было реализовать такие методы, как Arrays.sort().

Вам, вероятно, лучше использовать здесь «настоящую» коллекцию Java.

Чтобы ответить на более общий вопрос: Да, если вы хотите использовать параметризованный инвариантный тип в методе контрвариантного класса, вы должны указать верхнюю границу в сигнатуре для этого метода.

person Kevin Wright    schedule 15.10.2010
comment
Обратите внимание, что массивы Java ковариантны, как бы странно это ни звучало. Инвариантность Scala приводит к некоторым проблемам, особенно с методами, ожидающими Object[]. - person Daniel C. Sobral; 15.10.2010

Связано с этим вопрос. Вы можете либо пропустить проверку на отклонение

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

или использовать привязку вида

scala> abstract class Circle[T<%T] extends Shape[T]{
     | def draw(points: Array[_<:T]): Unit
     | }
defined class Circle
person Vasil Remeniuk    schedule 15.10.2010
comment
@missingfactor да, scala может предложить слишком много :) - person Vasil Remeniuk; 17.10.2010
comment
Хм, хотя он компилируется, но при вызове метода рисования из Java я получаю следующую ошибку: Circle: method ‹init›()V not found - person halfwarp; 18.10.2010
comment
@halfwarp вы использовали аннотацию или границы просмотра? - person Vasil Remeniuk; 18.10.2010