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 ??

È stato utile?

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)
  }
}
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top