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 Throwable
s, 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.
精彩评论