Scala生活中的一个可悲事实是,如果你实例化一个List [Int],你可以验证你的实例是一个List,你可以验证它的任何单个元素是一个Int,但不是它是一个List [ Int],可以很容易地验证:
scala> List(1,2,3) match {
| case l : List[String] => println("A list of strings?!")
| case _ => println("Ok")
| }
warning: there were unchecked warnings; re-run with -unchecked for details
A list of strings?!
Run Code Online (Sandbox Code Playgroud)
-unchecked选项将责任直接归咎于类型擦除:
scala> List(1,2,3) match {
| case l : List[String] => println("A list of strings?!")
| case _ => println("Ok")
| }
<console>:6: warning: non variable type-argument String in type pattern is unchecked since it is eliminated by erasure
case l …Run Code Online (Sandbox Code Playgroud) 我所知道的TypeTags就是他们以某种方式取代了Manifest.互联网上的信息很少,并没有让我对这个主题有很好的认识.
所以,如果有人在TypeTag上分享了一些有用的资料,包括例子和流行的用例,我会很高兴.我们也欢迎详细的解答和解释.
(这个问题类似于我看过的很多问题,但大多数问题对我正在做的事情都不够具体)
背景:
我的程序的目的是让使用我的程序的人轻松制作自定义"插件",然后编译并加载到程序中以供使用(与我的程序中实现的不完整,慢速解析器相比).我的程序允许用户将代码输入到预定义的类中,该类扩展了与我的程序一起打包的编译类.他们将代码输入到文本窗格中,然后我的程序将代码复制到被覆盖的方法中.然后将其保存为.java文件(几乎)为编译器准备好了.该程序运行javac(java编译器),并将保存的.java文件作为输入.
我的问题是,我如何得到它,以便客户端(使用我的编译程序)将这个java文件(扩展我的InterfaceExample)保存在他们的计算机上的任何地方,让我的程序编译它(不说"找不到符号:InterfaceExample" )然后加载它并调用doSomething()方法?
我一直在看Q&A使用的是反射或ClassLoader,几乎描述了如何编译它,但没有一个对我来说足够详细/我完全不理解它们.
我可以得到一个Type从TypeTag[A]使用tpe方法.但我还可以从类型中恢复类型标记吗?
import scala.reflect.runtime.{universe => ru}
import ru.{Type, TypeTag}
def forward[A](implicit tt: TypeTag[A]): Type = tt.tpe
def backward(t: Type): TypeTag[_] = ???
Run Code Online (Sandbox Code Playgroud)
原因是我有一个API使用类型标签作为地图的键,但在某些时候我只有类型并删除了标签.
我有createOld方法,我需要覆盖,我无法改变它.我想使用TypeTag模式匹配提供的类型createNew.我们的目标是找出如何调用createNew的createOld.我目前的理解是编译器没有足够的关于Ain createOld方法的类型信息,如果它还没有TypeTag[A].
object TypeTagFromClass {
class C1
class C2
// How to get TypeTag[A] needed by createNew?
def createOld[A](c: Class[A]): A = createNew ???
def createNew[A : TypeTag]: A = {
val result = typeOf[A] match {
case a if a =:= typeOf[C1] => new C1()
case a if a =:= typeOf[C2] => new C2()
}
result.asInstanceOf[A]
}
}
Run Code Online (Sandbox Code Playgroud) 在 Scala 反射中,通常可以使用 TypeCreator 从 Type 构造 TypeTag:
object TypeUtils {
import ScalaReflection.universe._
def createTypeTag[T](
tpe: Type,
mirror: reflect.api.Mirror[reflect.runtime.universe.type]
): TypeTag[T] = {
TypeTag.apply(
mirror,
NaiveTypeCreator(tpe)
)
}
case class NaiveTypeCreator(tpe: Type) extends reflect.api.TypeCreator {
def apply[U <: reflect.api.Universe with Singleton](
m: reflect.api.Mirror[U]): U#Type = {
// assert(m eq mirror, s"TypeTag[$tpe] defined in $mirror cannot be migrated to $m.")
tpe.asInstanceOf[U#Type]
}
}
Run Code Online (Sandbox Code Playgroud)
不幸的是,事实证明 的输出createTypeTag不可序列化,这与编译时推理创建的 typeTag 不同:
import java.io.{ByteArrayOutputStream, ObjectOutputStream}
import org.apache.spark.sql.catalyst.ScalaReflection
import org.scalatest.FunSpec
class TypeTagFromType extends FunSpec { …Run Code Online (Sandbox Code Playgroud) 简单的问题,如何TypeTag从类名获得?
所以基本上TypeTag相当于Class.forNameJava.
注意:Manifest不会在这里为我做,我需要一个TypeTag.虽然如果有一种方法可以从清单转到typetag,那也可以,因为我可以从类名中获取清单.
所以,我正在使用 Scala 反射库,并且我正在尝试检查一个方法是否符合给定的类型。为简化起见,我试图仅检查其输出。
我现在拥有的是:
val returnType = methodSymbol.returnType
// returnType: reflect.runtime.universe.Type = java.lang.String
Run Code Online (Sandbox Code Playgroud)
所以,我可以读到它是一个字符串,但它有这种可怕的类型reflect.runtime.universe.Type。我到底如何比较检查这个返回类型是否是一个简单的字符串?我什至尝试使用足够简单的 TypeTags,但是将 a 转换Type为 aTypeTag是一项巨大的努力,我不相信这样简单的任务无法通过更简单的方式完成。
那么,我如何将它与 String 进行比较并简单地返回一个布尔值?我想简单地调用 atoString()并尝试将其解析回正常类型,但这对代码来说真的很恶心,IMO。此外,我不能简单地指定方法名称,因为我正在处理方法列表,稍后会提供更多方法。
我已经看到了一些问题,甚至这个(在我看来,荒谬复杂的)回答有关如何将类型转换为TypeTag,但同样,我被复杂的这样一个简单的任务级别百思不得其解。我已经在考虑拔掉我稀少的头发了。帮助表示赞赏。
编辑:我已经设法对字符串本身进行比较,但没有对返回字符串的方法进行比较。
为了比较 String 返回类型,我正在做:
val returnType = methodSymbol.returnType
returnType =:= typeTag[String].tpe
Run Code Online (Sandbox Code Playgroud)
但是,当我尝试使用继承和方法检查它时,使用<:<,它不起作用。澄清一下,B 扩展了 Trait A,类型签名是() => B,但我在编码时无法匹配
val typeSig = methodSymbol.typeSig
typeSig <:< typeTag[() => A].tpe
Run Code Online (Sandbox Code Playgroud) 给定一个Type命名inner,我想创建一个新的Type,表示Option包含与...相同类型的类型inner.
例如,执行此操作的方法的签名可能类似于:
def createOptionType(inner: Type): Type = {
typeOf[Option[inner]] // this line is pseudocode
}
Run Code Online (Sandbox Code Playgroud)
这个答案有部分帮助,但是使用了泛型方法,而在这种情况下,我传递了一个具体类型,使泛型不可用.
scala ×8
reflection ×5
types ×2
compilation ×1
dynamic ×1
external ×1
java ×1
load ×1
reification ×1
scala-2.10 ×1
type-erasure ×1