【问题标题】:Structural subtyping reflection结构子类型反射
【发布时间】:2012-11-01 21:01:30
【问题描述】:

我们能否使用函数f外部的反射获得val s: String的类型?

val f = (r: {val s: String}) => {
}

【问题讨论】:

  • 在2.9或2.10以下还是没关系?
  • 2.9 或 2.10 无关紧要。但我通常使用 2.9.2。
  • 我非常怀疑在不使用编译器的情况下在 2.9 中是否可行。在 2.10 中,反射 api 可能允许检查 r 的类型。
  • 使用this info 我试图用 2.10.0-RC1 反映匿名函数如下,但坚持它擦除匿名函数参数的类型 - 这可能是一个错误,我会报告:import reflect.runtime._, universe._; currentMirror.reflectClass(currentMirror.reflect(f).symbol).symbol.typeSignature.member(newTermName("apply")).asTerm.alternatives.map(_.typeSignature)
  • 这不是错误。 currentMirror.reflect(f) 反映运行时值,因此它只能访问运行时类型信息,在编译过程中会被删除。

标签: scala reflection structural-typing


【解决方案1】:
scala> import scala.reflect.runtime.{universe => ru}
import scala.reflect.runtime.{universe=>ru}

scala> import scala.reflect.runtime.universe._
import scala.reflect.runtime.universe._

scala> def typeOf[T: ru.TypeTag](x: T) = ru.typeOf[T] // capture compile-time type info
typeOf: [T](x: T)(implicit evidence$1: reflect.runtime.universe.TypeTag[T])reflect.runtime.universe.Type

scala> val f = (r: {val s: String}) => {}
f: AnyRef{val s: String} => Unit = <function1>

scala> val tpe = typeOf(f)
tpe: reflect.runtime.universe.Type = scala.AnyRef{val s: String} => Unit

scala> ru.showRaw(tpe)
res0: String = TypeRef(ThisType(scala), scala.Function1, List(RefinedType(List(TypeRef(ThisType(scala), newTypeName("AnyRef"), List())), Scope(newTermName("s"))), TypeRef(ThisType(scala), scala.Unit, List())))

scala> val ru.TypeRef(_, _, refinement :: _) = tpe
refinement: reflect.runtime.universe.Type = scala.AnyRef{val s: String}

使用 Scala 反射,还可以为结构类型生成模拟,如下所示:https://gist.github.com/4008389。链接的 gist 使用工具箱和运行时反射来实现这一点,但这个场景看起来也可以通过宏实现。

【讨论】:

  • 您使用哪个版本的 Scala?我收到关于最后一条语句的警告:warning: abstract type pattern reflect.runtime.universe.TypeRef is unchecked since it is eliminated by erasure
  • 需要导入。它将 TypeRef 的类标记带入范围,从而消除了未经检查的警告。
  • 有没有办法创建细化实例?
  • @sndyuk 我不这么认为。细化类型仅在类型检查期间使用,不会为它们生成类。所以一开始我们没有什么要实例化的。
  • @sschaef 这是因为TypeRef 是一个抽象类型(scala.reflect.api.Types#TypeRef)并且抽象类型在编译过程中被删除,失去了它们的身份。因此,当模式匹配器尝试发出 something.isInstanceOf[TypeRef] 时,这会导致未经检查的警告。然而,当范围内有一个隐式类标签时,模式匹配器可以利用它来发出类似classtag.runtimeClass.isAssignableFrom(something.getClass) 的东西(其中类标签指向底层的 scala.reflect.internal.Types#TypeRef,它是一个成熟的类,而不是抽象类型)。
猜你喜欢
  • 2015-09-13
  • 1970-01-01
  • 1970-01-01
  • 2018-12-27
  • 2017-11-12
  • 2021-01-26
  • 1970-01-01
  • 2013-01-10
  • 2022-09-27
相关资源
最近更新 更多