Как я могу создать тип Option во время выполнения (отражение)?

Используя отражение, я определил тип вещи во время выполнения, t: Type. Теперь я хочу создать новый тип опции [t]. Как я могу это сделать?

val t: Type = ...
val optT: Type = ???  // Option of whatever t is

Почему я хочу этого: у меня есть функция-обработчик, которая работает с типом. Во время компиляции у меня есть что-то вроде этого:

trait Thing { name: String }
case class BigThing(name: String) extends Thing

case class Stuff[T <: Thing]( id: Int, maybeThing: Option[T] ) // contrived

def handler( t: Type ): Output = {...}

Я могу предположить, что если у меня есть класс типа Stuff, то у него есть член mayThing типа Object[T] или даже Object[Thing]. Скажем, во время выполнения я могу определить, что конкретный объект имеет T = BigThing, поэтому я хочу передать Option[BigThing], а не Option[T] или Option[Thing] в обработчик(). Вот почему я пытаюсь создать исполняемый тип Option[BigThing].

Я пробовал следующее, но Scala это не понравилось:

val newType = staticClass(s"Option[${runtimeTypeTAsString}]")

person Greg    schedule 17.02.2019    source источник
comment
Откуда t?   -  person Brian McCutchon    schedule 17.02.2019
comment
Таким образом, учитывая, что t: Type представляет значение типа T, вам нужен метод def makeOptionType(t: Type): Type, который возвращает Type, представляющий значение типа Option[T]?   -  person Tim    schedule 17.02.2019


Ответы (1)


Согласно руководству.

существует три способа создания экземпляра Type.

  • через метод typeOf на scala.reflect.api.TypeTags, который подмешивается в Universe (самый простой и распространенный).
  • Стандартные типы, такие как Int, Boolean, Any или Unit, доступны через доступный юниверс.
  • Создание вручную с использованием заводских методов, таких как typeRef или polyType на scala.reflect.api.Types (не рекомендуется).

Используя третий способ,

import scala.reflect.runtime.universe._

class MyClass

val t: Type = typeOf[MyClass] //pckg.App.MyClass

val mirror = runtimeMirror(ClassLoader.getSystemClassLoader)

val optT: Type = mirror.universe.internal.typeRef(
  definitions.PredefModule.typeSignature, 
  definitions.OptionClass, 
  List(t)
) // Option[pckg.App.MyClass]

val optT1 : Type = typeOf[Option[MyClass]]

optT =:= optT1 // true
person Dmytro Mitin    schedule 17.02.2019