Parametrico funzione tipo + richiede una stringa come secondo parametro?
-
30-09-2019 - |
Domanda
class TestClass[T](val x: T) { def +(other: TestClass[T]) = x + other.x }
questa definizione mi dà il seguente errore di compilazione:
errore: tipo non corrispondente;
trovato: T
richiesta: String
def + (altro: TestClass [T]) = x + other.x
Non è possibile utilizzare Int o Double come un parametro di tipo e l'uso, oltre a Scala ??
Soluzione
In primo luogo, il messaggio di errore è fuorviante. scalac cerca di trovare un metodo +
sul valore x
. Questo non esiste sul tipo T
, che potrebbe essere qualsiasi tipo. Questo si chiama un parametro di tipo illimitata. Quindi cerca di applicare e vista implicita. Predef.any2stringadd
si inserisce il disegno di legge.
È possibile disattivare questa conversione implicita, e vedere il vero errore:
~/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
In C ++, il tipo di controllo viene effettuata dopo il parametro di tipo viene fornito, in ciascun sito chiamata. Quindi, questo stile di codice avrebbe funzionato. In Scala, il metodo generico deve essere di tipo controllato alla sua definizione, sulla base solo sui limiti dei tipi astratti.
Come suggerito da VonC, si potrebbe desiderare di fornire un contesto legato al parametro type T
Per vincolare se ad un tipo che ha un corrispondente istanza del Numeric
trait.
class TestClass[T: Numeric](val x: T) {
def +(other: TestClass[T]): T = {
val num = implicitly[Numeric[T]]
import num._
x + other.x
}
}
Ecco come questo appare con tutte le impliciti esplicitati:
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)
}
}