Ответ 1
catching
выглядит как-то вроде вызова метода, не так ли? Это так, но на самом деле возвращает экземпляр класса Catch
; он не принимает прямого аргумента. Этот класс имеет два метода, которые особенно полезны для устранения исключений (и еще нескольких для обнаружения нескольких исключений). Первый -
def opt [U >: T] (body: ⇒ U) : Option[U]
который используется здесь, вы даете ему что-то, что может вызвать исключение, и оно вернет Some(result)
, если все будет в порядке, и None
, если целевое исключение было поймано:
scala> type NFE = NumberFormatException
defined type alias NFE
scala> import scala.util.control.Exception._
import scala.util.control.Exception._
scala> catching(classOf[NFE]).opt( "fish".toInt )
res0: Option[Int] = None
scala> catching(classOf[NFE]).opt( "42".toInt )
res1: Option[Int] = Some(42)
Затем вы можете справиться с этим с помощью map
или filter
или getOrElse
или всего, что вы используете для работы с параметрами.
Другим полезным методом является either
, который возвращает экземпляр Left(exception)
, если выбрано исключение, и Right(result)
, если это не так:
scala> catching(classOf[NFE]).either( "fish".toInt )
res2: Either[Throwable,Int] = Left(java.lang.NumberFormatException: For input string: "fish")
scala> catching(classOf[NFE]).either( "42".toInt )
res3: Either[Throwable,Int] = Right(42)
Затем вы можете использовать fold
или сопоставить параметр или все, что вам нравится делать с eithers.
Обратите внимание, что вы можете определить один улавливатель и использовать его несколько раз (так что вам не нужно создавать объект catcher каждый раз, когда вы, например, разбираете целое число):
scala> val catcher = catching(classOf[NFE])
catcher: util.control.Exception.Catch[Nothing] = Catch(java.lang.NumberFormatException)
scala> catcher.opt("42".toInt)
res4: Option[Int] = Some(42)
scala> catcher.opt("fish".toInt)
res5: Option[Int] = None
Изменить: как отмечает Даниил в комментариях, это создает временный Catch[Option]
; учитывая сигнатуры метода, нет простого способа просто исключить исключения ловушки и генерировать параметры без создания каких-либо дополнительных объектов. Это напоминает мне, почему я пишу свои собственные методы, чтобы сделать именно это:
def optNFE[T](t: => T) = try { Some(t) } catch {case nfe: NFE => None}
optNFE( "fish".toInt ) // gives None
optNFE( "42".toInt ) // gives Some(42)