我坐在一个大约10000 LoC的项目前。我必须将此项目从Scala 2.9更新到2.10。这样做得很好,但由于清单,我收到了许多弃用警告。
在使用stackoverflow和许多其他站点的搜索功能之后,我没有那么多问题。我想总结一下;关键点是:
TypeTags和ClassTag比Manifest和ClassManifest好得多。特别是你可以使用这些作为同义词(TypeTags< - > Manifests和ClassTags< - > ClassManifest)
TypeTag比ClassTag更强大,ClassTag更受限制TypeTags。 我的第一个问题:在此项目中,经常使用方法manifest[T].erasure.getSimpleName
。现在我不仅可以将其切换为typeTag[T].runtimeClass.getSimpleName
,因为代码无法编译,但是classTag[T].runtimeClass.getSimpleName
会编译。 这会影响语义吗?(注意:方法erasure
也已弃用;您必须改为使用runtimeClass
)
第二个问题: Scala 2.9中清单的类型检查有点像:manifest[T] <:< manifest[A]
。在Scala 2.10中,我会写这个typeOf[T] <:< typeOf[A]
。但<:<
已被弃用?!
我可以将TypeTag转换为ClassTag吗?即:如果我只使用清单进行类型检查(Nr.3)和名称提取(Nr.2):我能将每个Manifest / ClassManifest重命名为ClassTag吗?
答案 0 :(得分:5)
是的,您通常具有等效TypeTag <-> Manifest
和ClassTag <-> ClassManifest
。除了有些事情以前没有直接等效的Manifest处理,因为这些操作被深入到反射API中,就像Manifest
对象上的工厂方法一样。
ClassTag
现在基本上只用于获取运行时(擦除)类的东西。它主要用于创建数组,但您可以毫无问题地将其用于其他目的。是的,classTag[T].runtimeClass
是新的manifest[T].erasure
,完全等同于它。
这是变化最大的地方。 2.10引入了new reflection API,如果你想回答关于类型的具体问题(比如“A <:< B
?”),你应该使用它。而类型的反射API的入口点是...... TypeTag
。
假设A
和T
的类型标签在范围内,新的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。
我认为没有直接的方法可以从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
实例,或者您可以传递的真实类名,稍后使用反射加载,我认为您别无选择,只需要{ {1}}也是..
修改:我刚刚找到this SO question,是的,可以从ClassTag
获得ClassTag
。遗憾的是,反射库中没有任何帮助方法。
修改2 :根据要求,以下是从TypeTag
转换为TypeTag
的方式:
ClassTag