Premièrement, le message d'erreur est trompeur. scalac essaie de trouver une méthode +
sur la valeur x
. Cela n'existe pas sur le type T
, qui pourrait être de n'importe quel type. C'est ce qu'on appelle un paramètre de type non borné. Donc, il essaie d'appliquer et de voir implicitement. Predef.any2stringadd
correspond à la facture.
Vous pouvez désactiver cette conversion implicite, et voir la vraie erreur:
~/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
En C++, la vérification de type est effectué après le paramètre de type est fourni à chaque site d'appel. Donc, ce style de code fonctionnerait. Dans Scala, la méthode générique doit être vérifiée par type à sa définition, basée uniquement sur les limites des types abstraits.
Comme suggéré par VonC, vous pourriez vouloir fournir un contexte lié au paramètre de type T
pour contraindre à un type qui a une instance correspondante du trait Numeric
.
class TestClass[T: Numeric](val x: T) {
def +(other: TestClass[T]): T = {
val num = implicitly[Numeric[T]]
import num._
x + other.x
}
}
Voilà comment cela ressemble à toutes les implicits explicites:
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)
}
}
Voir http://stackoverflow.com/questions/2096414/addition-with-generic-type-parameter-in-scala et http://stackoverflow.com/questions/1252915/scala-how-to-define-generic-function-parameters pour les débutants: vous aurez peut-être besoin ici d'un type '' Numeric' implicite. – VonC