Scala classOf для параметра типа


80

Я пытаюсь создать универсальный метод для обновления объектов с помощью scala / java, но не могу получить класс для параметра типа.

Вот мой код:

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

Я получаю ошибку

тип класса требуется, но найдено T

Я знаю, что в java это невозможно, но возможно ли это вообще в Scala?

Благодаря!


Ответы:


93

Из манифеста является устаревшим (Поскольку Scala 2.10.0) это обновленный ответ -

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

Вы должны использовать ClassTagвместо ClassManifest и .runtimeClassвместо.erasure

Исходный ответ - Да, это можно сделать с помощью манифестов:

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

О боже, это потрясающе! Хотел бы я знать об этом раньше!
Darkzaelus 01

1
Вы даже можете написать manifest[T]вместо implicitly[Manifest[T]].
Жан-Филипп Пелле,

1
@ mericano1 они стали неотъемлемой частью языка, и, я думаю, манифесты больше не являются экспериментальной функцией,
Василь Ременюк 01

12
@ mericano1 Одно обновление: Manifestи ClassManifestтеперь устарели, будучи заменены на TypeTagи ClassTag, соответственно, в Scala 2.10.
Daniel C. Sobral

9
Вместо того, чтобы classTag[T].runtimeClassмне было нужно classTag[T].runtimeClass.asInstanceOf[Class[T]]. Кто-нибудь знает почему?
kosii

6

Мне помог ответ Василия и Максима.

Лично я предпочитаю синтаксис, в котором implicitиспользуется для добавления таких параметров (представленное : ClassTagявляется сокращением для него. Итак, здесь, на случай, если кто-то еще считает, что это лучший способ:

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

Отказ от ответственности: я не компилировал вышеупомянутое, но мой собственный аналогичный код работает таким образом.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.