Как обрабатывать нулевые входные параметры в 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 и пробелы будут удалены.