Во-первых, сообщение об ошибке вводит в заблуждение.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)
}
}