Параметрический тип + функция требует строки в качестве второго параметра?
-
30-09-2019 - |
Вопрос
class TestClass[T](val x: T) { def +(other: TestClass[T]) = x + other.x }
Это определение дает мне следующую ошибку компиляции:
Ошибка: несоответствие типа;
Найдено: Т.
Требуется: строка
def + (Другое: testclass [t]) = x + white.x
Разве невозможно использовать INT или Double в качестве параметра типа и использование добавления в Scala ??
Решение
Во-первых, сообщение об ошибке вводит в заблуждение. Scalac пытается найти метод +
по значению x
. Отказ Это не существует на типе T
, что может быть любой тип вообще. Это называется неограниченным типом параметра. Таким образом, он пытается подать заявку и неявное представление. Predef.any2stringadd
соответствует законопроекту.
Вы можете отключить это неявное преобразование и увидеть реальную ошибку:
~/code/scratch: cat plus.scala
import Predef.{any2stringadd => _, _}
class TestClass[T](val x: T) {
def +(other: TestClass[T]) = x + other.x
}
~/code/scratch: scalac plus.scala
plus.scala:4: error: value + is not a member of type parameter T
def +(other: TestClass[T]) = x + other.x
^
one error found
В C ++ проверка типа выполняется после предоставления параметра типа на каждом сайте вызова. Так что этот стиль кода будет работать. В SCALA общий метод должен быть типа проверяется по его определению, основываясь только на границах абстрактных типов.
Как предложено VONC, вы можете предоставить контекст, связанный на параметре типа T
ограничить, если к типу, который имеет соответствующий экземпляр Numeric
черта.
class TestClass[T: Numeric](val x: T) {
def +(other: TestClass[T]): T = {
val num = implicitly[Numeric[T]]
import num._
x + other.x
}
}
Вот как это выглядит со всеми недостатками, сделанными явными:
class TestClass[T]{
implicit <paramaccessor> private[this] val evidence$1: Numeric[T] = _;
def this(x: T)(implicit evidence$1: Numeric[T]): TestClass[T] = {
TestClass.super.this();
()
};
def +(other: TestClass[T]): T = {
val num: Numeric[T] = scala.Predef.implicitly[Numeric[T]](TestClass.this.evidence$1);
import num._;
num.mkNumericOps(TestClass.this.x).+(other.x)
}
}