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!


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);
  ...
 }
}

¡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.

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.