【问题标题】:Is it possible to convert a TypeTag to a Manifest?是否可以将 TypeTag 转换为 Manifest?
【发布时间】:2014-04-30 08:57:28
【问题描述】:

我们的库使用 TypeTag,但现在我们需要与另一个需要 Manifest 的库进行交互。有什么简单的方法可以从 TypeTag 创建 Manifest?

【问题讨论】:

标签: scala reflection scala-2.10


【解决方案1】:

如果您在存在TypeTag 时天真地尝试调用Manifest,编译器会提示您解决方案:

import reflect.runtime.universe._
import reflect.ClassTag

def test[A : TypeTag] = manifest[A]

error: to create a manifest here, it is necessary to interoperate with the type
tag `evidence$1` in scope.
however typetag -> manifest conversion requires a class tag for the corresponding
type to be present.
to proceed add a class tag to the type `A` (e.g. by introducing a context bound)
and recompile.
   def test[A : TypeTag] = manifest[A]
                                   ^

因此,如果您在范围内有ClassTag,编译器将能够创建必要的Manifest。你有两个选择:

  • TypeTag 所在处添加第二个上下文,如:

    def test[A : TypeTag : ClassTag] = manifest[A] // this compiles
    
  • 或先将TypeTag 转换为ClassTag,然后请求Manifest

    def test[A](implicit ev: TypeTag[A]) = {
      // typeTag to classTag
      implicit val cl = ClassTag[A]( ev.mirror.runtimeClass( ev.tpe ) )
    
      // with an implicit classTag in scope, you can get a manifest
      manifest[A]
    }
    

【讨论】:

    【解决方案2】:

    gourlaysama 的答案使用 Class[_],因此类型参数被删除。我想出了一个在这里保留类型参数的实现:How to maintain type parameter during TypeTag to Manifest conversion?

    代码如下:

      def toManifest[T:TypeTag]: Manifest[T] = {
        val t = typeTag[T]
        val mirror = t.mirror
        def toManifestRec(t: Type): Manifest[_] = {
          val clazz = ClassTag[T](mirror.runtimeClass(t)).runtimeClass
          if (t.typeArgs.length == 1) {
            val arg = toManifestRec(t.typeArgs.head)
            ManifestFactory.classType(clazz, arg)
          } else if (t.typeArgs.length > 1) {
            val args = t.typeArgs.map(x => toManifestRec(x))
            ManifestFactory.classType(clazz, args.head, args.tail: _*)
          } else {
            ManifestFactory.classType(clazz)
          }
        }
        toManifestRec(t.tpe).asInstanceOf[Manifest[T]]
      }
    

    【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-11-21
    • 2010-09-28
    • 1970-01-01
    • 2021-10-28
    • 2021-10-15
    • 2020-11-24
    • 1970-01-01
    相关资源
    最近更新 更多