2010-06-27 7 views
2

class TestClass[T](val x: T) { def +(other: TestClass[T]) = x + other.x }Le type + fonction paramétrique nécessite une chaîne comme deuxième paramètre?

cette définition me donne l'erreur de compilation suivante:

erreur: incompatibilité de type;
trouvé: T
requis: String
def + (autre: TestClass [T]) = x + other.x

est-il pas possible d'utiliser Int ou Double comme un paramètre de type et d'utiliser plus de Scala ??

+1

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

Répondre

9

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) 
    } 
} 
Questions connexes