加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 服务器 > 安全 > 正文

scala – 从类[A]中获取TypeTag [A]

发布时间:2020-12-16 09:56:40 所属栏目:安全 来源:网络整理
导读:我有createOld方法,我需要覆盖,我不能改变它.我想使用TypeTag在createNew中模式匹配提供的类型.目标是找出如何从createOld调用createNew.我目前的理解是编译器在createOld方法中没有足够的关于A的类型信息,如果它还没有TypeTag [A]. object TypeTagFromClass
我有createOld方法,我需要覆盖,我不能改变它.我想使用TypeTag在createNew中模式匹配提供的类型.目标是找出如何从createOld调用createNew.我目前的理解是编译器在createOld方法中没有足够的关于A的类型信息,如果它还没有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]
  }
}

解决方法

可以使用Scala反射从类创建TypeTag,但我不确定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.")
  })    
}

但是,如果您不需要检查通用参数和完整的Scala类型信息,则不需要完整的TypeTag.你可以使用ClassTags:

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]

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

从createOld调用这个createNew比使用TypeTags的那个简单得多:

def createOld[A](c: Class[A]): A = createNew(ClassTag[A](c))

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读