开发者

Can I avoid redundantly casting a Throwable when using catching(...).either?

I'm using util.control.Exception.catching to convert internal exceptions into an exception type specific to my library:

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
    }
}

Unfortunately, this doesn't work. Applying the Catch returned by either doesn't return Either[Exception,Foo], it returns Either[Throwable,Foo]. But I've already told catching I want it to catch only subtypes of Exception, not all Throwables, and internally it's already matched an Exception.

Am I using this correctly? Is there no way I can convince catching to return the exception it catches as an instance of the class of exceptions I asked it to catch? Is my best bet to just add a redundant asInstanceOf[Exception]? I'd rather not if I can avoid it, as the catching inst开发者_如何学Cance could logically be created elsewhere, and I'd like to get a compile error if I one day change it to catching[Throwable] without changing ErrorOccurredDuringFoo, not a runtime error when the cast to Exception fails.


Catch isn't parameterised on Throwable, only on the result type. The only way to downcast the Throwable type is with the mkCatcher method:

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

But, Catch takes a Catcher[T] – which is really just an alias for a PartialFunction[Throwable, T].

As a case statement is a PartialFunction we can use pattern matching:

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


You could write it like this:

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

It is interesting that it doesn't complain about missing cases.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜