Могу ли я избежать избыточного использования Throwable при использовании catching (...). - PullRequest
3 голосов
/ 13 сентября 2011

Я использую 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] без изменения ErrorOccurredDuringFoo, а не ошибка времени выполнения при сбое приведения к Exception.

Ответы [ 2 ]

4 голосов
/ 13 сентября 2011

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].

В качестве оператора case является PartialFunction, мы можем использовать сопоставление с образцом:

val c: Catcher[Foo] = {
  case e: MyException => throw new ErrorOccurredDuringFoo(e)
}
catching(c)(fooInternals)
1 голос
/ 14 сентября 2011

Вы могли бы написать это так:

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

Интересно, что он не жалуется на пропущенные дела.

...