例外情况应该是案例类吗?

时间:2013-01-23 12:26:44

标签: scala exception case-class

我的自定义异常类型应该是case class es吗?

从好的方面来说,我得到了提取器。

在负面,我得到了不正确的相等语义。但我可以通过覆盖equals来避免这种情况。

因此,在概念层面上,使它们成为case class es?

是否有意义

3 个答案:

答案 0 :(得分:35)

这当然是非常主观的,但在我看来,将异常类作为案例类是一种好习惯。 主要的理由是,当您捕获异常时,您正在进行模式匹配,并且案例类在模式匹配中使用得更好。 这是一个利用在catch块中使用模式匹配的全部功能的示例,当使用case类异常时:

object IOErrorType extends Enumeration {
  val FileNotFound, DeviceError, LockedFile = Value
}
case class IOError(message: String, errorType: IOErrorType.Value) extends  Exception(message)

def doSomeIO() { throw IOError("Oops, file not found!", IOErrorType.FileNotFound)  }

try {
  doSomeIO()
} catch {
  case IOError( msg, IOErrorType.FileNotFound ) =>
    println("File not found, please check the path! (" + msg + ")")
}

在这个例子中,我们只有一个例外,但它包含一个errorType字段,用于何时想知道发生的确切错误类型(通常这是通过异常层次结构建模的,我不是说这是好还是坏,这个例子只是说明性的)。因为IOError是一个案例类,所以我只需要case IOError( msg, IOErrorType.FileNotFound )来捕获错误类型IOErrorType.FileNotFound的异常。如果没有我们通过case类免费获得的提取器,我将不得不每次捕获异常,然后重新抛出,以防我实际上不感兴趣,这肯定更冗长。

你说case类给你不正确的相等语义。我不这么认为。 ,因为异常类的编写者可以决定什么是等义语义。毕竟当你捕获异常时,catch块是你通常根据类型决定要捕获的异常的地方,但可以基于其字段的值或其他内容,如我的例子中所示。关键是异常类的相等语义与此无关。

答案 1 :(得分:18)

通过创建例外案例类而丢失的一个常见习惯是创建子类的异常层次结构的模式,子类用于表示错误条件的更高特异性。案例类不能被子类化。

答案 2 :(得分:4)

我喜欢RégisJean-Gilles的回答。但是如果你有充分的理由不参加案例课程(请参阅Dave Griffith的答案),你可以像上面的例子一样使用普通的课程并且不应用:

object IOErrorType extends Enumeration {
  val FileNotFound, DeviceError, LockedFile = Value
}
object IOError {
  def unapply(err: IOError): Option[(String, IOErrorType.Value)] = Some(err.message, err.errorType)
}
class IOError(val message: String, val errorType: IOErrorType.Value) extends  Exception(message)

def doSomeIO() { throw new IOError("Oops, file not found!", IOErrorType.FileNotFound) }

try {
  doSomeIO()
} catch {
  case IOError( msg, IOErrorType.FileNotFound ) =>
    println("File not found, please check the path! (" + msg + ")")
}