scala - 更新到 Scala 2.10 时出现 list /类型标签问题

标签 scala manifest scala-2.10


我正坐在一个大约 10000 LoC 的项目前面。我必须将此项目从 Scala 2.9 更新到 2.10。这做得很好,但由于 list ,我收到了许多弃用警告。

在使用了stackoverflow和许多其他网站的搜索功能后,我没有那么多疑问了。我想总结一下;要点是:

  1. TypeTags 和 ClassTags 比 Manifest 和 ClassManifest 好得多。特别是您可以将它们用作同义词(TypeTags <-> Manifests 和 ClassTags <-> ClassManifest)

  2. TypeTags 比 ClassTags 更强大,而 ClassTags 是更受限制的 TypeTags。 我的第一个问题:在这个项目中,方法 manifest[T].erasure.getSimpleName经常被使用。现在我不能只将其切换为 typeTag[T].runtimeClass.getSimpleName因为代码无法编译,但带有 classTag[T].runtimeClass.getSimpleName它会编译。 这会影响语义吗?(注意:方法 erasure 也已弃用;您必须使用 runtimeClass 来代替)

  3. 第二个问题:Scala 2.9 中 list 的类型检查是这样的:manifest[T] <:< manifest[A] 。在 Scala 2.10 中,我会写这个 typeOf[T] <:< typeOf[A] 。但是<:<已弃用?!

  4. 我可以将 TypeTag 转换为 ClassTag 吗?即:如果我仅使用 list 进行类型检查(第 3 个)和名称提取(第 2 个):我可以将每个 Manifest/ClassManifest 重命名为 ClassTag 吗?

最佳答案

  1. 是的,您基本上具有等价的 TypeTag <-> ManifestClassTag <-> ClassManifest 。除了过去由 list 处理的一些内容没有直接等效项之外,因为这些操作已更深入地移至反射 API 中,例如 Manifest 上的工厂方法。对象。

  2. ClassTag现在基本上只用于获取某些东西的运行时(删除)类。它的主要用途是创建数组,但您可以将它用于其他目的,没有问题。所以是的,classTag[T].runtimeClass是新的manifest[T].erasure并且完全等同于它。

  3. 这是变化最大的地方。 2.10介绍new reflection API ,当您想要回答有关类型的特定问题(例如“A <:< B吗?”)时,应该使用它。类型的反射 API 的入口点是...其 TypeTag .

    假设类型标签为AT在范围内,新的manifest[T] <:< manifest[A]确实是typeOf[T] <:< typeOf[A] 。方法<:<此处并未弃用,see the scaladoc 。然而,有一个已弃用的 <:<ClassTag因为ClassManifest曾经有一个,并且 ClassTag是新的ClassManifest .

    请参阅有关 Common Operations on Types 的部分反射(reflection)指南,以及SO问题What is a TypeTag and how do I use it .

  4. 我认为没有直接的方法可以从 TypeTag 转到到 ClassTag 。可以这样想:

    • 如果您需要子类型或类型相等性检查,则不能使用 ClassTag ,您需要一个TypeTag ;

    • 如果您还需要该类型的名称,您可以从TypeTag获取它。 :typeOf[T].typeSymbol.name.decoded 。这将为您提供删除的名称,就像您过去获取的类名一样( List 代表 List[Int] ,或 Map 代表 Map[String, Int] )。这与获取实际 Class 的名称略有不同。尽管。如果您需要完整的未删除名称( List[Int] ), typeOf[T].normalize.toString就够了。

    • 如果您也绝对需要 Class实例,或者您可以传递并稍后通过反射加载的真实类名,我认为您别无选择,只能要求 ClassTag也是..

      编辑:我刚刚找到 this SO question ,所以是的,有可能得到 ClassTag来自TypeTag 。遗憾的是反射库中没有为此提供辅助方法。

      编辑 2:根据要求,以下是如何从 TypeTag 进行转换至ClassTag :

      import reflect.runtime.universe._
      import reflect.ClassTag
      
      def classTag2[T: TypeTag]: ClassTag[T] = {
        ClassTag[T]( typeTag[T].mirror.runtimeClass( typeTag[T].tpe ) )
      }
      
      // example:
      
      def doSomething[T : TypeTag] = {
        val c = classTag2[T]
        c.runtimeClass.getName
      }
      

关于scala - 更新到 Scala 2.10 时出现 list /类型标签问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17898839/

相关文章:

scala - 为什么值类仅限于 AnyVal?

scala - 在playframework 2/scala中上传多个大文件和其他表单数据

.net - Visual Studio 应用程序资源 : 'Icon and manifest' vs 'Resource file' issues

scala - 为 Future 值和超时创建 memoize

scala - OpenPDF/iText 损坏的文件

c# - 非托管代码是否需要 list 文件?

windows - Windows 上的 Qt DLL 部署

scala - 更新不可变 AST 的最简单方法是什么?

scala - 将数组[数组[双]]转换为数组[双]

scala - 如何在 Scala 中打印扩展宏?