更新到Scala 2.10时清单/类型标记出现问题

时间:2013-07-27 14:26:03

标签: scala manifest scala-2.10


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

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

  1. TypeTags和ClassTag比Manifest和ClassManifest好得多。特别是你可以使用这些作为同义词(TypeTags< - > Manifests和ClassTags< - > ClassManifest)

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

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

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

1 个答案:

答案 0 :(得分:5)

  1. 是的,您通常具有等效TypeTag <-> ManifestClassTag <-> ClassManifest。除了有些事情以前没有直接等效的Manifest处理,因为这些操作被深入到反射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部分和SO问题What is a TypeTag and how do I use it

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

    • 如果您需要进行子类型或类型等式检查,则无法使用ClassTag,需要TypeTag;

    • 如果您还需要该类型的名称,则可以从TypeTagtypeOf[T].typeSymbol.name.decoded获取该名称。这将为您提供已删除的名称,就像您以前获得的类名一样(ListList[Int]MapMap[String, Int]。这与获取实际Class的名称略有不同。如果您需要完整的未删除名称(List[Int]),typeOf[T].normalize.toString就足够了。

    • 如果您还需要一个Class实例,或者您可以传递的真实类名,稍后使用反射加载,我认为您别无选择,只需要{ {1}}也是..

      修改:我刚刚找到this SO question,是的,可以从ClassTag获得ClassTag。遗憾的是,反射库中没有任何帮助方法。

      修改2 :根据要求,以下是从TypeTag转换为TypeTag的方式:

      ClassTag