Как обрабатывать нулевые входные параметры в Scala
Я знаю, что в Scala метод никогда не должен возвращаться null
... но как насчет входных параметров? Учитывая следующий фрагмент кода...
object MyObject {
def myMethod(p: String): Option[String] = {
if (p == null) throw new IllegalArgumentException("p is null.")
...
}
}
... я проверить p
исправить? Есть какие-нибудь рекомендации?
4 ответов
соглашение заключается в том, что код Scala не использует нули (с небольшим количеством исключений, которые должны быть немедленно исправлены при использовании этих библиотечных функций).
таким образом, null от Scala является признаком того, что что-то пошло не так (по крайней мере,PBCAK), поэтому вы можете также бросить исключение. Это не рутинная работа, это что-то серьезно облажался. Ловите исключение везде, где вы ловите серьезные ошибки. Ловить IllegalArgumentException
вместо a NullPointerException
добавляет никакой дополнительной информации. Просто оставьте оригинал в покое.
если код исходит из Java, канонический способ борьбы с ним-обернуть его в Option
, который преобразует null
to None
. Тогда вам, вероятно, даже не нужно выбрасывать исключение; просто верните None
.
def myMethod(p: String) = Option(p).map(_.toLowerCase)
если вы не можете продолжить, когда он равен null, вам нужно рассмотреть, поможет ли информативное исключение. Option(p).orElse(throw new IllegalArgumentException("Null!"))
один компактный способ выражения исключение-бросание сантиментов.
в Scala 2.10 вы также можете обернуть вещи в scala.util.Try(...)
который автоматически поймает и упакует исключение для вас. Если вы хотите упакованное исключение вместо брошенного, это путь. (И использовать Try
вместо Option
.)
import scala.util.Try
def myMethod(p: String) = Try(p.toLowerCase)
наконец, для более общей обработки альтернативных решений, использование Either
. Соглашение для обработки ошибок заключается в том, что ожидаемым результатом является Right(whatever)
, а Left(whatever)
указывает на то, что что-то пошло не так.
есть несколько способов, и ваш путь-это одна.
вы также можете использовать:
require(p != null, "p is null.")
или "более функциональным" способом было бы использовать Option
:
def myMethod(p: String): Option[String] = {
// no exception
for {
pp <- Option(p)
} yield p + " foo bar"
}
edit:
или, если вы хотите ошибку без исключения, вы можете использовать Either
:
def myMethod(p: String): Either[Exception, String] = {
if(p == null) Left(new IllegalArgumentException("p is null."))
else Right(p + "foo bar")
}
идиома Scala по существу "никогда не используйте нулевые значения". Поэтому, если вы не пишете API, который должен вместить грязных пользователей Java, я бы просто не беспокоился об этом. В противном случае вы в конечном итоге вставите эту проверку шаблона для каждого параметра в каждом методе, который вы пишете.
ваши красивые однострочные методы
def square(x: String): String = math.pow(x.toInt, 2).toInt.toString
превратится во что-то неловкое, как
def square(x: String): String =
if (x == null) throw new NullPointerException()
math.pow(x.toInt, 2).toInt.toString
}
или
def square(x: String): String = Option(x) match {
case Some(x) => math.pow(x.toInt, 2).toInt.toString
case None => throw new NullPointerException()
}
- Какой ужас.
мой любимый подход-это что-то вроде:
object HandlingInputValidation {
def main(args: Array[String]) = {
println("A1: " + handleInput("Correct ") + " END")
println("A2: " + handleInput("Correct") + " END")
println("A3: " + handleInput("") + " END")
println("A4: " + handleInput(" ") + " END")
println("A5: " + handleInput(null) + " END")
}
def handleInput(data: String): Option[String] = {
Option(data).map(_.trim.toLowerCase)
}
}
В этом случае null
будет None
и пробелы будут удалены.