gpt4 book ai didi

scala - 从 Class[A] 中获取 TypeTag[A]

转载 作者:行者123 更新时间:2023-12-04 14:45:05 26 4
gpt4 key购买 nike

我有 createOld我需要覆盖并且我无法更改它的方法。我想使用 TypeTag模式匹配 createNew 中提供的类型.目标是找出如何调用createNew来自 createOld .我目前的理解是编译器没有足够的关于 A 的类型信息。在 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]
}
}

最佳答案

可以创建 TypeTag来自 Class使用 Scala 反射,虽然我不确定 TypeCreator 的这个实现是否是绝对正确的:

import scala.reflect.runtime.universe._

def createOld[A](c: Class[A]): A = createNew {
val mirror = runtimeMirror(c.getClassLoader) // obtain runtime mirror
val sym = mirror.staticClass(c.getName) // obtain class symbol for `c`
val tpe = sym.selfType // obtain type object for `c`
// create a type tag which contains above type object
TypeTag(mirror, new TypeCreator {
def apply[U <: Universe with Singleton](m: api.Mirror[U]) =
if (m eq mirror) tpe.asInstanceOf[U # Type]
else throw new IllegalArgumentException(s"Type tag defined in $mirror cannot be migrated to other mirrors.")
})
}

但是,您并不需要完整的 TypeTag如果您不需要检查泛型参数和完整的 Scala 类型信息。您可以使用 ClassTag为此:
def createNew[A: ClassTag]: A = {
val result = classTag[A].runtimeClass match {
case a if a.isAssignableFrom(classOf[C1]) => new C1()
case a if a.isAssignableFrom(classOf[C2]) => new C2()
}
result.asInstanceOf[A]
}

或者加上一些隐含的糖:
implicit class ClassTagOps[T](val classTag: ClassTag[T]) extends AnyVal {
def <<:(other: ClassTag[_]) = classTag.runtimeClass.isAssignableFrom(other.runtimeClass)
}

def createNew[A: ClassTag]: A = {
val result = classTag[A] match {
case a if a <<: classTag[C1] => new C1()
case a if a <<: classTag[C2] => new C2()
}
result.asInstanceOf[A]
}

您可以通过使用普通的旧 Java newInstance() 来进一步简化它。方法:
def createNew[A: ClassTag]: A = classTag[A].runtimeClass.newInstance().asInstanceOf[A]

当然,这仅在您不需要不同类的不同构造函数参数时才有效。

调用 createNew来自 createOld比带有 TypeTag 的那个简单得多年代:
def createOld[A](c: Class[A]): A = createNew(ClassTag[A](c))

关于scala - 从 Class[A] 中获取 TypeTag[A],我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22970209/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com