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

scala – 匹配可能不是详尽的警告是不正确的

发布时间:2020-12-16 18:09:37 所属栏目:安全 来源:网络整理
导读:所以 scala编译器抱怨模式匹配可能不是foo方法的穷举,我想知道为什么.这是代码: abstract class Foo { def foo(that: Foo): Unit = (this,that) match { case (Foo_1(),Foo_1()) = //case 1 case (Foo_1(),Foo_2()) = //case 2 case (Foo_2(),Foo_1()) = //
所以 scala编译器抱怨模式匹配可能不是foo方法的穷举,我想知道为什么.这是代码:

abstract class Foo {
    def foo(that: Foo): Unit = (this,that) match {
        case (Foo_1(),Foo_1()) => //case 1
        case (Foo_1(),Foo_2()) => //case 2
        case (Foo_2(),Foo_1()) => //case 3
        case (Foo_2(),Foo_2()) => //case 4
            // Compiler warning
    }

    def fooThis(): Unit = this match {
        case Foo_1() => //do something
        case Foo_2() => //do something
            // Works fine
    }

    def fooThat(that: Foo): Unit = that match {
        case Foo_1() => //do something
        case Foo_2() => //do something
            // Works fine
    }
}
case class Foo_1() extends Foo
case class Foo_2() extends Foo

这是错误:

Warning:(5,32) match may not be exhaustive.
It would fail on the following inputs: (Foo(),_),(Foo_1(),(Foo_2(),(_,Foo()),Foo_1()),Foo_2()),_)
    def foo(that: Foo): Unit = (this,that) match {

由于这个和Foo类型,并且Foo只能是Foo_1或Foo_2类型,因此foo中的情况都是可能的组合.

为了完整起见,我添加了fooThis和fooThat,并表明匹配Foo_1和Foo_2就足够了.编译器消息表明还有其他类型可以匹配(即Foo和_).

那么为什么会出现这个警告呢?

有关:

> Scala bug: fixed in 2.12.0-M4.我的scala欢迎辞:

Welcome to Scala 2.12.1 (Java HotSpot(TM) Client VM,Java 1.8.0_131).

> Scala bug: false match not exhaustive warning on (unsealed,sealed) tuple

编辑

一旦你使用元组,编译器似乎就会抱怨.如果我们将一个虚拟变量添加到fooThis,如下所示

def fooThis(): Unit = (this,Foo_1()) match {
    case (Foo_1(),_) => //do something
    case (Foo_2(),_) => //do something
}

我们得到以下编译器警告

Warning:(13,27) match may not be exhaustive.
It would fail on the following input: (_,_)
    def fooThis(): Unit = (this,Foo_1()) match {

解决方法

Scala编译器不会为非密封特征(如您的Foo)提供详尽的匹配警告.这解释了为什么fooThis和fooThat编译没有警告.

如果你想在这里发出警告(你应该,因为它们在运行时比MatchError异常更好),你有几个选择:

>让Foo密封.这会创建一个ADT,这样可以安全地进行模式匹配,因为当您忘记案例时,您将获得详尽的警告.选项是您可能从标准库中熟悉的ADT.在这里,你已经有了Foo_1和Foo_2的案例,所以你不会得到一个详尽的警告.但如果你忘了这两种情况,你会的.你可能想让Foo_1和Foo_2成为最终决赛.
>保持Foo未密封,使用Typelevel Scala并启用其-Xlint:strict-unsealed-patmat警告.

另一方面,Scala编译器将为最终案例类(如Tuple2)提供详尽的匹配警告,这是您在foo方法中匹配的内容.

要回答“为什么会显示警告?”,请考虑如果我们这样做会发生什么:

case class Foo3() extends Foo
val foo3 = Foo3()
foo3.foo(foo3)

(答案:它在运行时抛出MatchError.)

警告是Scala编译器帮助您在运行时避免异常的方法.如果你想让警告消失,你可以:

>让Foo密封(再次创建一个ADT),防止Foo3潜入其他地方.
>添加通配符案例_ => ….
>取消选中匹配:((this,that):@unchecked)match {….

不要做3号,因为当有人介绍Foo3时,它会让你在运行时容易受到MatchErrors的攻击.

所以,也许问题不是“为什么foo中的匹配会产生警告”,而是“为什么fooThis和foo中的匹配不会产生警告”.

(编辑:李大同)

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

    推荐文章
      热点阅读