Scala classOf para parámetro de tipo

80

Estoy tratando de crear un método genérico para actualizaciones de objetos usando scala / java pero no puedo obtener la clase para un parámetro de tipo.

Aquí está mi código:

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

El error que obtengo es

tipo de clase requerido pero T encontrado

Sé que en Java no puedes hacerlo, pero ¿es esto posible en Scala?

¡Gracias!

mericano1
fuente

Respuestas:

93

Due Manifest está en desuso (desde Scala 2.10.0) esta es la respuesta actualizada:

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

Deberías usar en ClassTaglugar de ClassManifest y en .runtimeClasslugar de.erasure

Respuesta original: sí, puede hacerlo usando manifiestos:

object WorkUnitController extends Controller {     
 def updateObject[T: ClassManifest](toUpdate: T, body: JsonObject){
  val source = gson.fromJson(body, classManifest[T].erasure);
  ...
 }
}
Vasil Remeniuk
fuente
¡Oh Dios, eso es asombroso! ¡Ojalá hubiera sabido esto antes!
Darkzaelus
1
Incluso puedes escribir en manifest[T]lugar de implicitly[Manifest[T]].
Jean-Philippe Pellet
1
@ mericano1 se han convertido en una parte esencial del lenguaje y, creo, los manifiestos ya no son una característica experimental
Vasil Remeniuk
12
@ mericano1 Una actualización: Manifesty ClassManifestahora están en desuso, habiendo sido reemplazados con TypeTagy ClassTag, respectivamente, en Scala 2.10.
Daniel C. Sobral
9
En lugar de lo classTag[T].runtimeClassque necesitaba classTag[T].runtimeClass.asInstanceOf[Class[T]]. ¿Alguien sabe por qué?
kosii
6

La respuesta de Vasil y Maxim me ayudó.

Personalmente, prefiero la sintaxis donde implicitse usa para agregar tales parámetros (la que se presenta : ClassTages una abreviatura para ello. Así que aquí, en caso de que alguien más también vea que esta es una mejor manera:

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

Descargo de responsabilidad: no compilé lo anterior, pero mi propio código similar funciona de esta manera.

akauppi
fuente