我正坐在一个大约 10000 LoC 的项目前面。我必须将此项目从 Scala 2.9 更新到 2.10。这做得很好,但由于 list ,我收到了许多弃用警告。
在使用了stackoverflow和许多其他网站的搜索功能后,我没有那么多疑问了。我想总结一下;要点是:
TypeTags 和 ClassTags 比 Manifest 和 ClassManifest 好得多。特别是您可以将它们用作同义词(TypeTags <-> Manifests 和 ClassTags <-> ClassManifest)
TypeTags 比 ClassTags 更强大,而 ClassTags 是更受限制的 TypeTags。 我的第一个问题:在这个项目中,方法
manifest[T].erasure.getSimpleName
经常被使用。现在我不能只将其切换为typeTag[T].runtimeClass.getSimpleName
因为代码无法编译,但带有classTag[T].runtimeClass.getSimpleName
它会编译。 这会影响语义吗?(注意:方法erasure
也已弃用;您必须使用runtimeClass
来代替)第二个问题:Scala 2.9 中 list 的类型检查是这样的:
manifest[T] <:< manifest[A]
。在 Scala 2.10 中,我会写这个typeOf[T] <:< typeOf[A]
。但是<:<
已弃用?!我可以将 TypeTag 转换为 ClassTag 吗?即:如果我仅使用 list 进行类型检查(第 3 个)和名称提取(第 2 个):我可以将每个 Manifest/ClassManifest 重命名为 ClassTag 吗?
最佳答案
是的,您基本上具有等价的
TypeTag <-> Manifest
和ClassTag <-> ClassManifest
。除了过去由 list 处理的一些内容没有直接等效项之外,因为这些操作已更深入地移至反射 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 的部分反射(reflection)指南,以及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
实例,或者您可以传递并稍后通过反射加载的真实类名,我认为您别无选择,只能要求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/