Функция Scala, которая извлекает Class[_] из общего

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

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 ответа

Проще говоря: 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.

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

Вы не можете эту информацию от 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вокруг.

Другие вопросы по тегам