使用捕捉(...)时,我可以避免冗余地施放Throwable吗?

时间:2011-09-13 02:49:01

标签: exception scala

我正在使用util.control.Exception.catching将内部异常转换为特定于我的库的异常类型:

import util.control.Exception._

abstract class MyException extends Exception

case class ErrorOccurredDuringFoo(e : Exception) extends MyException

def foo : Foo = {
    catching(classOf[Exception]) either { fooInternals } match {
        case Left(e) => throw ErrorOccurredDuringFoo(e)
        case Right(v) => v
    }
}

不幸的是,这不起作用。应用Catch返回的either不返回Either[Exception,Foo],它会返回Either[Throwable,Foo]。但我已经告诉catching我希望它只捕获Exception的子类型,而不是所有Throwable的子类型,并且内部已经匹配Exception

我是否正确使用此功能?难道我无法说服catching将它捕获的异常作为我要求它捕获的异常类的实例返回吗?我最好还是添加一个多余的asInstanceOf[Exception]?我宁愿不要,如果我可以避免它,因为catching实例可以在其他地方逻辑地创建,并且如果我有一天将其更改为catching[Throwable]而不更改{我想得到编译错误{1}},当转换为ErrorOccurredDuringFoo失败时,不是运行时错误。

2 个答案:

答案 0 :(得分:4)

Catch未在Throwable上参数化,仅在结果类型上参数化。向下转换Throwable类型的唯一方法是使用mkCatcher方法:

val c = catching[Foo](
  mkCatcher(
    (t: Throwable) => t.getClass == classOf[MyException],
    (e: MyException) => throw new ErrorOccurredDuringFoo(e)))
c(fooInternals)

但是,Catch需要Catcher[T] - 这实际上只是PartialFunction[Throwable, T]的别名。

作为案例陈述 PartialFunction,我们可以使用模式匹配:

val c: Catcher[Foo] = {
  case e: MyException => throw new ErrorOccurredDuringFoo(e)
}
catching(c)(fooInternals)

答案 1 :(得分:1)

你可以这样写:

def foo : Foo = {
    catching(classOf[Exception]) either { fooInternals } match {
        case Left(e: Exception) => throw ErrorOccurredDuringFoo(e)
        case Right(v) => v
    }
}

有趣的是,它不会抱怨遗失的案件。