首页 文章

模式匹配的选择器是详尽的

提问于
浏览
2

看着Scala doc for sealed classes,它说:

如果模式匹配的选择器是密封类的实例,则模式匹配的编译可以发出警告,诊断出给定的一组模式并非详尽无遗,即在运行时可能出现MatchError-时间 .

我不太明白他们在这一段中的含义 . 我的理解是,如果一个switch case没有涵盖所有可能性,那么我们将在编译时收到警告,说我们可能在运行时遇到错误 . 它是否正确?

我觉得很奇怪,因为我们怎样才能涵盖交换机案例中的所有场景?我们必须匹配所有可能的字符串,这只是愚蠢的,所以我认为我的理解是不正确的 . 请问有人在说清楚吗?

3 回答

  • 4

    我觉得很奇怪,因为我们怎样才能涵盖交换机案例中的所有场景?我们必须匹配所有可能的字符串

    是的,如果选择器的类型为 String (除了它不是 sealed 类,因为它是Scala概念而 String 是Java类) .

    这只是愚蠢的

    不需要 . 对于字符串,你只需要一个包罗万象的案例,例如:

    val x: String = ...
    x match {
      case "a" => ...
      case "b" => ...
      case _ => ...
    }
    

    是一个详尽的匹配:无论 x 是什么,它都匹配其中一个案例 . 更有用的是,您可以:

    val x: Option[A] = ...
    x match {
      case Some(y) => ...
      case None => ...
    }
    

    并且即使没有一个包罗万象的情况,编译器也会意识到匹配是详尽的 .

  • 0

    该段落的内容是,如果你有一个固定的层次结构,如下所示:

    sealed trait Foo
    class Bar extends Foo
    class Baz extends Foo
    class Zab extends Foo
    

    然后,当您对其进行模式匹配时,编译器可以推断您是否尝试匹配扩展密封特征的所有可能类型,在此示例中:

    def f(foo: Foo) = foo match {
         | case _: Bar => println("bar")
         | case _: Baz => println("baz")
         | }
    
    <console>:13: warning: match may not be exhaustive.
    It would fail on the following input: Zab()
           def f(foo: Foo) = foo match {
                             ^
    f: (foo: Foo)Unit
    

    注意document的开头说:

    密封类可能无法直接继承,除非继承模板在与继承类相同的源文件中定义 .

    这是Scala独有的,不能用Java完成 . 即使在同一文件中声明,Java中的 final 类也不能继承 . 这就是为什么这个逻辑不适用于Scala中的 String ,它是 java.lang.String 的别名 . 只能为符合上述条件的Scala类型发出编译器警告 .

  • 3

    通配符允许我们覆盖所有场景 .

    something match {
      case one => ...
      case two => ...
      case _ => ...
    }
    

    只要所有其他情况不匹配,就会选择它;也就是说,这是默认情况 . 更多信息here .

相关问题