Scala classOf für Typparameter

80

Ich versuche, eine generische Methode für Objektaktualisierungen mit scala / java zu erstellen, aber ich kann die Klasse für einen Typparameter nicht abrufen.

Hier ist mein Code:

object WorkUnitController extends Controller {     
 def updateObject[T](toUpdate: T, body: JsonObject){
  val source = gson.fromJson(body, classOf[T]);
  ...
 }
}

Der Fehler, den ich bekomme, ist

Klassentyp erforderlich, aber T gefunden

Ich weiß, in Java kann man das nicht, aber ist das in Scala überhaupt möglich?

Vielen Dank!

mericano1
quelle

Antworten:

93

Due Manifest ist veraltet (seit Scala 2.10.0) Dies ist die aktualisierte Antwort -

import scala.reflect.ClassTag
import scala.reflect._

object WorkUnitController extends Controller {
  def updateObject[T: ClassTag](toUpdate: T, body: JsonObject){
    val source = gson.fromJson(body, classTag[T].runtimeClass)
    ???
  }
}

Sie sollten ClassTaganstelle von ClassManifest und .runtimeClassanstelle von verwenden.erasure

Ursprüngliche Antwort - Ja, das können Sie mit Manifesten tun:

object WorkUnitController extends Controller {     
 def updateObject[T: ClassManifest](toUpdate: T, body: JsonObject){
  val source = gson.fromJson(body, classManifest[T].erasure);
  ...
 }
}
Vasil Remeniuk
quelle
Oh Gott, das ist unglaublich! Ich wünschte, ich hätte früher davon gewusst!
Darkzaelus
1
Sie können sogar schreiben manifest[T]statt implicitly[Manifest[T]].
Jean-Philippe Pellet
1
@ mericano1 sie sind ein wesentlicher Bestandteil der Sprache geworden, und ich denke, Manifeste sind kein experimentelles Merkmal mehr
Vasil Remeniuk
12
@ mericano1 Ein Update: Manifestund ClassManifestjetzt veraltet sind, mit ersetzt wurde TypeTagund ClassTag2,10 auf Scala, respectively.
Daniel C. Sobral
9
Anstelle von classTag[T].runtimeClassmir brauchte classTag[T].runtimeClass.asInstanceOf[Class[T]]. Weiß jemand warum?
Kosii
6

Die Antwort von Vasil und Maxim hat mir geholfen.

Persönlich bevorzuge ich die Syntax, in implicitder solche Parameter hinzugefügt werden (die dargestellte : ClassTagist eine Abkürzung dafür. Für den Fall, dass jemand anderes dies auch als besseren Weg ansieht:

import scala.reflect.ClassTag

object WorkUnitController extends Controller {
  def updateObject[T](toUpdate: T, body: JsonObject)(implicit tag: ClassTag[T]){
    val source = gson.fromJson(body, tag.runtimeClass)
    ???
  }
}

Haftungsausschluss: Ich habe das oben Gesagte nicht kompiliert, aber mein eigener ähnlicher Code funktioniert auf diese Weise.

Akauppi
quelle