我有一个案例类层次结构来编码一些请求和处理错误:
sealed trait OpError
sealed trait RequestErrorType
sealed trait ProcessingErrorType
final case class InvalidEndpoint(reason: String) extends RequestErrorType
final case class InvalidParameters(reason: String) extends RequestErrorType
final case class InvalidFormat(response: String) extends ProcessingErrorType
final case class EntityNotFound(id: Long) extends ProcessingErrorType
final case class RequestError(errorType: RequestErrorType) extends OpError
final case class ProcessingError(errorType: ProcessingErrorType) extends OpError
如果我在所有模式中编写简单匹配:
def printMatches(error: OpError): Unit = error match {
case RequestError(InvalidEndpoint(reason)) => //print something
case RequestError(InvalidParameters(reason)) => //print something
case ProcessingError(InvalidFormat(format)) => //print something
case ProcessingError(EntityNotFound(entityId)) => //print something
}
编译器给我一个关于缺少匹配的警告:
match may not be exhaustive.
It would fail on the following input: ProcessingError(_)
def printMatches(error: OpError): Unit = error match {
但ProcessingError接收的ProcessingErrorType只有两个扩展名:InvalidFormat和EntityNotFound,两者都在模式匹配中考虑。我错过了什么?
更奇怪的是,如果我将InvalidParameters或InvalidEndpoint的参数类型更改为String *,我就不会收到错误:
final case class InvalidParameters(reason: String*) extends RequestErrorType
有什么想法吗?
答案 0 :(得分:4)
这是一个确认的错误。 I filed a bug report for this已经为Scala 2.12.0-M4修复了它。
答案 1 :(得分:1)
非常有趣!不幸的是,我还没找到答案。我一直在围绕着http://www.scala-lang.org/files/archive/spec/2.11/08-pattern-matching.html#constructor-patterns,但我还没有真正找到有效的解释。
这是一个更简单的演示(希望你不要介意):
sealed abstract class ClassOne
case class ClassOneImpl() extends ClassOne
sealed abstract class ClassTwo()
case class ClassTwoImpl() extends ClassTwo
sealed abstract class Foo
case class FooOne(x: ClassOne) extends Foo
case class FooTwo(x: ClassTwo) extends Foo
def printMatches(st: Foo): Unit = st match {
case FooOne(ClassOneImpl()) => println()
case FooTwo(ClassTwoImpl()) => println()
}
我观察到以下两个修改中的每一个都删除了警告:
1)更改FooOne
和FooTwo
个签名,以便取代ClassOne
和ClassTwo
,而不是ClassOneImpl
和ClassTwoImpl
2)删除FooOne
或FooTwo
,以便只有一个案例类扩展Foo
(在模式匹配中仅导致一个案例)。
也许我们可以提交问题,看看他们说了什么?
答案 2 :(得分:0)
您可以使用未经检查的注释来帮助编译器:
... = (error: @unchecked) match ...
但你应该确定,你的比赛是详尽无遗的。
答案 3 :(得分:0)
我认为详尽匹配适用于单个继承级别。
RequestErrorType
和ProcessingErrorType
是构造函数的一部分,其中未检查详尽性。
你可以从阅读代码中看到它,但似乎编译器没有。