为什么我在scala比赛中有一个不可能的案例?

Geo*_*org 5 scala pattern-matching case-class

在下面的例子中,在第二个中case我会期望与第一个相同的编译错误case,但它编译.为什么?

object CaseMatching extends App {

  case class Id(value: Long)
  object Id { val zero = Id(0) }
  case class Name(value: String)
  case class IdName(id: Id, name: Name)

  IdName(Id(0), Name("A")) match {
    case IdName(_, Id(0)  ) => // does not compile (as expected)
    case IdName(_, Id.zero) => // does compile (but should not ?)
    case IdName(Id.zero, _) => println("OK") // this is OK and will match
    case _ =>
  }

}
Run Code Online (Sandbox Code Playgroud)

为什么相关?- 我花了大部分时间来找出为什么从未遇到过以下情况:case TreeEntry(_, Some(child), _, _, NodeType.DIR, _, _)那就是,因为NodeType在第4个字段而不在第5个字段中.如果编译器告诉我,我会很感激!

som*_*ytt 5

最简单的答案:使用Namefinal足以说服编译器这zero不是一个。请参阅此问题和环境。

它会在类型测试上发出警告,这是一个 isInstanceOf:

<console>:15: warning: fruitless type test: a value of type CaseMatching.Name cannot also be a CaseMatching.Id
           case IdName(_, _: Id) =>
                             ^
Run Code Online (Sandbox Code Playgroud)

但在测试平等时则不然,因为平等是普遍存在的。

这里还有一个不错的,case IdName(_, Id) =>

<console>:15: error: pattern type is incompatible with expected type;
 found   : CaseMatching.Id.type
 required: CaseMatching.Name
Note: if you intended to match against the class, try `case _: Id`
           case IdName(_, Id) =>
                          ^
Run Code Online (Sandbox Code Playgroud)

你想要的是:

scala> IdName(Id(0), Name("A")) match { case IdName(_, id: Id.zero.type) => }
<console>:21: warning: fruitless type test: a value of type Name cannot also be a Id (the underlying of Id.zero.type)
              IdName(Id(0), Name("A")) match { case IdName(_, id: Id.zero.type) => }
                                                                         ^
Run Code Online (Sandbox Code Playgroud)

单例类型仅包含该值,因此它用于eq测试;作为类型测试,它还会发出警告。(它使用的eq是而不是equals本周的。)

不确定这对你来说有多远,但是:

scala> :pa
// Entering paste mode (ctrl-D to finish)

sealed trait Id { def value: Long }
case class Nonzero(value: Long) extends Id
case object Zero extends Id { val value = 0L }
case class Name(value: String)
case class IdName(id: Id, name: Name)

// Exiting paste mode, now interpreting.

scala> IdName(Zero, Name("A")) match { case IdName(_, Zero) => 1 }
<console>:14: error: pattern type is incompatible with expected type;
 found   : Zero.type
 required: Name
              IdName(Zero, Name("A")) match { case IdName(_, Zero) => 1 }
                                                             ^
Run Code Online (Sandbox Code Playgroud)