Функция Scala, которая извлекает Class [_] из общего - PullRequest
0 голосов
/ 15 ноября 2018

Итак, что я хочу сделать:

def foo(clazz: Class[_]): Unit = {
  val int = classOf[Int]
  val str = classOf[String]
  val opt = classOf[Option[_]]
  clazz match {
    case `int` => println("INT!")
    case `str` => println("STRING!")
    case `opt` => foo(clazz.getTheTypeOutOfGeneric) // <- I think you get the idea 
  }
}

Для заданного clazz: Class[_ :< Option[_]] Я бы хотел найти тип, с которым он был создан, поэтому в итоге я получу INT! при работе свведите Option[Int].Как мне это сделать?Нужно ли использовать отражения?

Ответы [ 2 ]

0 голосов
/ 15 ноября 2018

Вы не можете получить эту информацию из Class из-за стирания типа. Для этого вам понадобится ClassTag:

import scala.reflect.runtime.universe._
def foo[T : TypeTag](clazz: Class[T]) = clazz match {
   ...
   case `opt` => foo(typeOf[T].typeArgs.head)
   ...
}

Но прежде чем сделать это, проверьте Type и TypeTag, а также другие полезности в scala.reflect.runtime.universe - более чем вероятно, вы найдете более простой и элегантный способ реализовать то, что вам нужно с помощью этого материала , чем прохождение сырых Class вокруг.

0 голосов
/ 15 ноября 2018

Проще говоря: Class не несет никакой информации о параметрах типа.

Так, например,

classOf[Option[Int]] eq classOf[Option[String]]

вернет true.Обратите внимание, что оператор eq проверяет равенство ссылок, поэтому эти два объекта на самом деле являются одним и тем же объектом!

Попробуйте!

Даже с отражением, которое вы выиграли 'я не могу получить информацию, которой просто нет.


Я бы порекомендовал отказаться от использования значений Class и вместо этого использовать параметры типа и классы типов для специального полиморфизма.Точное решение зависит от того, что вы действительно пытаетесь сделать.

Но вот пример того, как работают классы типов:

def get[F[_], A](a: F[A])(implicit ex: Extractor[A]): Unit = ex.extract

trait Extractor[A] {
  def extract: Unit
}

implicit val intExtractor = new Extractor[Int] {
  def extract: Unit = println("I am doing something for Int!")
}

implicit val strExtractor = new Extractor[String] {
  def extract: Unit = println("I am doing something for String!")
}

val a = Some(1)

get(a)

Вывод:

I am doing something for Int!

Попробуйте!

Для получения дополнительной информации я бы порекомендовал прочитать Руководство астронавта Type Shapeless , которое (помимо обучения вас о Shapeless) поможет вам понять большеОбщие аспекты общего программирования в Scala.

Надеюсь, это поможет.

...