加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 服务器 > 安全 > 正文

使用TypeTag的泛型类型上的Scala模式匹配会产生警告而ClassTag不

发布时间:2020-12-16 09:51:18 所属栏目:安全 来源:网络整理
导读:我有两个非常相似的方法.唯一的区别是使用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显示编译警告,
我有两个非常相似的方法.唯一的区别是使用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显示:
抽象类型模式A是未选中的,因为它被擦除情况a消除了:A

为什么会有警告?为什么它只显示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:

The compiler tries to turn unchecked type tests in pattern matches into checked ones by wrapping a (_: T) type pattern as ct(_: T),where ct is the ClassTag[T] instance. Type tests necessary before calling other extractors are treated similarly. SomeExtractor(...) is turned into ct(SomeExtractor(...)) if T in SomeExtractor.unapply(x: T) is uncheckable,but we have an instance of ClassTag[T].

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”特征更加集成.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读