使用TypeTag的泛型类型上的Scala模式匹配会产生警告而ClassTag不
我有两个非常相似的方法.唯一的区别是使用ClassTag和TypeTag:
def matchClass[A: ClassTag](v: Any) = v match { case a: A => "it's A" case _ => "not A" } def matchType[A: TypeTag](v: Any) = ... // same code as matchClass 将为matchType显示编译警告,但不会为matchClass显示: 为什么会有警告?为什么它只显示TypeTag而不是ClassTag? 解决方法
您没有看到classTag的警告,因为该检查仅适用于:
scala> matchClass[Int]("aaa") res82: String = not A scala> matchClass[Int](5) res83: String = it's A 并不适用于typeTag: scala> matchType[Int](5) res84: String = it's A scala> matchType[Int]("aaa") res85: String = it's A 原因是对于classTags上的模式匹配(当它看到一个隐式时),编译器生成如下内容: case a: A if classTag[A].runtimeClass.isInstance(a) => ... 一般来说,没有办法为TypeTags获取runtimeClass(考虑编译和运行时,请参阅UPDATE以获取允许仅在运行时提取它的特定情况),这就是编译器不转换它们的原因.默认情况下,由于擦除,模式匹配在泛型(多态)类型上无法匹配,因此默认情况下您可以看到该警告: scala> def matchGeneric[A](v: Any) = | v match { | case a: A => "it's A" | case _ => "not A" | } <console>:28: warning: abstract type pattern A is unchecked since it is eliminated by erasure case a: A => "it's A" ^ matchGeneric: [A](v: Any)String 更新:正如@Seth Tisue提到的when a tag comes from run-time universe (only)你可以获得它的运行时类(但你必须先创建一个镜像). 参考: 根据ClassTag本身的scaladocs:
TypeTag scaladocs和语言规范本身没有提到TypeTags的任何此类功能 推测性解释 没有办法确定为什么某些功能是否被实现,所以任何推测都是固执的(并且超出SO范围,甚至不直接与您的问题相关,而是回答@Tom的评论).尽管如此(截至2.12)…… 这可能是因为“ClassTags只提供对类型的运行时类的访问”,并且是scala-library的一部分(即使它们的包是scala.reflect.),而TypeTags是单独(并且相当广泛)反射的一部分.因此,API意味着根据它们所处的宇宙来指代编译或运行时间,因此为那些编写额外的检查(在综合期间!!)不仅会令人困惑(对于用户而言),对语言开发人员来说也很难:合成本身在一个不同的(compiler)模块中,[合成]不依赖于reflection(只有scala-library),因为模式匹配合成正在早期的“patmat”阶段发生.此外,scala spec(12.3.4.2 Variance)提到使用ClassTag进行数组实例化的合成调整(非常推测性地)可能意味着ClassTag与“syntax sugar”特征更加集成. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |