匹配嵌套异常类型

时间:2014-12-12 14:42:24

标签: scala

我正在使用一些客户端库,并使用scala.util.control.Exception.ignoring

来使用一些忽略特定异常的代码
ignoring(classOf[ReallyNotThatExceptionalException]) {
  stuff()
}

现在该库已更改为将所有exceptionn包装在另一个异常类中,这迫使我将代码更改为:

try { stuff() }
catch {
  case e:WrapperException if e.getCause != null && e.getCause.isInstanceOf[ReallyNotThatExceptionalException] => { }
}

因此,我正在寻找一种更易读的方式来表达"捕捉由"引起的异常。

3 个答案:

答案 0 :(得分:13)

0 __的回答很好,但如果你没有被迫为每个潜在的异常写一个特定的对象(CausedByFoo)会更好。 碰巧的是,没有太多要改变以使用通用的CausedBy辅助对象:

class Foo(message: String) extends Exception(message)
class Bar(cause: Throwable) extends Exception(cause)

object CausedBy {
  def unapply(e: Throwable): Option[Throwable] = Option(e.getCause)
}

def test(block: => Unit): String = 
  try {
    block
    "ok"
  } catch {
    case CausedBy(ex: Foo) => "not ok: " + ex.getMessage
  }

test(println("hello"))
test(println("hello".toInt)) // uncaught exception
test(throw new Bar(new Foo("Ooops, foo error!"))) // caught

很明显,您可以将CausedBy用于任何例外情况(例如,通过执行case CausedBy(ex: Baz)

你甚至可以嵌套它来处理由异常引起的异常引起的异常(做case CausedBy(CausedBy(ex: Foo))

之类的事情

答案 1 :(得分:4)

catch块可以处理任何常规模式匹配,所以

class Foo extends Exception
class Bar(cause: Exception) extends Exception(cause)

object CausedByFoo {
  def unapply(e: Exception): Boolean = e.getCause match {
    case _: Foo => true
    case _ => false
  }
}

def test(block: => Unit): String = 
  try {
    block
    "ok"
  } catch {
    case CausedByFoo() => "not ok"
  }

test(println("hello"))
test(println("hello".toInt)) // uncaught exception
test(throw new Bar(new Foo)) // caught

答案 2 :(得分:0)

我调整了Régis的答案,以允许同时匹配外部和内部异常类型。

trait CausedBy[T <: Throwable] {
  def unapply(e: T): Option[Throwable] = Option(e.getCause)
}

object IOExceptionCausedBy extends CausedBy[IOException]

然后您可以像这样进行匹配:

try {
  // do some DB thing
} catch {
  case IOExceptionCausedBy(exception: PSQLException) =>
    // handle PSQL exception
}