Scala classOf dla parametru typu


80

Próbuję utworzyć ogólną metodę aktualizacji obiektów za pomocą scala / java, ale nie mogę uzyskać klasy dla parametru typu.

Oto mój kod:

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

Otrzymuję błąd

wymagany typ klasy, ale znaleziono T.

Wiem, że w Javie nie możesz tego zrobić, ale czy jest to w ogóle możliwe w scali?

Dzięki!


Odpowiedzi:


93

Wymagany Manifest jest przestarzały (od wersji 2.10.0) to jest zaktualizowana odpowiedź -

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

Należy używać ClassTagzamiast ClassManifest i .runtimeClasszamiast.erasure

Oryginalna odpowiedź - Tak, możesz to zrobić za pomocą manifestów:

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

O Boże, to niesamowite! Żałuję, że nie wiedziałem o tym wcześniej!
Darkzaelus

1
Możesz nawet manifest[T]zamiast tego pisać implicitly[Manifest[T]].
Jean-Philippe Pellet

1
@ mericano1 stały się istotną częścią języka i myślę, że manifesty nie są już funkcją eksperymentalną
Vasil Remeniuk

12
@ mericano1 Jedna zmiana: Manifesti ClassManifestsą obecnie przestarzałe, został zastąpiony TypeTagi ClassTag, odpowiednio, na Scala 2.10.
Daniel C. Sobral

9
Zamiast tego classTag[T].runtimeClasspotrzebowałem classTag[T].runtimeClass.asInstanceOf[Class[T]]. Czy ktoś wie dlaczego?
kosii,

6

Pomogła mi odpowiedź Wasila i Maxima.

Osobiście wolę składnię, w której implicitjest używana do dodawania takich parametrów (przedstawiony : ClassTagjest skrótem. Więc tutaj, na wypadek, gdyby ktoś inny również uznał to za lepszy sposób:

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

Zastrzeżenie: nie skompilowałem powyższego, ale mój własny podobny kod działa w ten sposób.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.