Параметрический тип + функция требует строку в качестве второго параметра? - PullRequest
2 голосов
/ 27 июня 2010

class TestClass[T](val x: T) { def +(other: TestClass[T]) = x + other.x }

это определение дает мне следующую ошибку компиляции:

ошибка: несоответствие типов;
найдено: T
требуется: String
def + (другое: TestClass [T]) = x + other.x

Разве нельзя использовать Int или Double в качестве параметра типа и использовать сложение в Scala ??

1 Ответ

9 голосов
/ 27 июня 2010

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