Scala模式匹配在嵌套的case类上并不详尽
我有一个case类层次结构来编码一些请求和处理错误:Scala模式匹配在嵌套的case类上并不详尽,scala,pattern-matching,Scala,Pattern Matching,我有一个case类层次结构来编码一些请求和处理错误: sealed trait OpError sealed trait RequestErrorType sealed trait ProcessingErrorType final case class InvalidEndpoint(reason: String) extends RequestErrorType final case class InvalidParameters(reason: String) ext
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的参数类型更改为字符串*,我不会得到错误:
final case class InvalidParameters(reason: String*) extends RequestErrorType
有什么想法吗?您可以通过未选中的注释帮助编译器:
... = (error: @unchecked) match ...
但是您应该确定,您的匹配是详尽无遗的。我认为详尽无遗的匹配在单个继承级别上起作用。
RequestErrorType
和ProcessingErrorType
是构造函数的一部分,其中未检查穷尽性
您可以从代码的阅读中看到它,但编译器似乎没有。非常有趣!不幸的是,我还没有找到答案。我一直在转来转去,但我还没有找到一个有效的解释 这里有一个简单的演示(希望您不介意): 我注意到以下两种修改都会删除警告:
1) 更改
FooOne
和FooTwo
签名,以代替ClassOne
和ClassTwoImpl
他们采用ClassOneImpl
和ClassTwoImpl
2) 删除
FooOne
或FooTwo
,这样只有一个case类扩展Foo
(这导致模式匹配中只有一个case)
也许我们可以提交一个问题,看看他们怎么说?这是一个已确认的错误。自那以后,Scala 2.12.0-M4已经修复了它。
printMatches(ProcessingError(新的ProcessingErrorType{}))
它不匹配此示例违反了密封的
契约。关于String*参数的奇怪行为,当一个case类有一个varargs参数时,这听起来像是Scala转向了穷举检查:true,但我希望编译器帮助我找出无效实例,而不是相反的方法。;)假设我从printMatches中注释掉RequestError(InvalidParameters(reason))的匹配,那么编译器让我知道我缺少了确切的变化:“匹配可能不是穷尽的。它会在以下输入上失败:RequestError(InvalidParameters(41;)”。所以我想编译器可以找出一些嵌套继承。我把它作为一个bug归档,它已经被修复并关闭了!耶!:)有关解决方法,请参阅此注释:
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()
}