scala - 在 Scala 中进行空检查的最佳实践

标签 scala

我明白 null在 Scala 中不受欢迎,并且应该始终将可选值包装在 Option 中(或“空类型”,如果有的话)。

优点很明显,永远不需要检查 null值,并且生成的代码更安全,更易于阅读。

然而在实践中,没有什么能阻止一个值成为 null - 规则不是由编译器强制执行的,更像是君子协定。例如,当与 Java API 交互时,这很容易中断。

是否有最佳实践?例如,假设我需要写一个 Url case 类,并且该类的实例可以从 java.net.URI 创建:

object Url {
  def apply(uri: URI): Url = Url(uri.getScheme, uri.getHost, uri.getRawPath)
}

case class Url(protocol: String, host: String, path: String) {
  def protocol(value: String): Url = copy(protocol = value)
  def host(value: String): Url = copy(host = value)
  def path(value: String): Url = copy(path = value)
}

URI实例可以返回 nullgetScheme , getHostgetRawPath .在 apply(URI) 中是否足以防止这些问题?方法(例如,使用 require 语句)?从技术上讲,为了完全安全,最好保护 protocol , hostpath辅助方法以及构造函数,但这听起来像是大量的工作和样板。

相反,防止已知接受/返回的 API 是否被认为是安全的 null值(在我们的示例中为 URI)并假设外部调用者不会通过 null值(value)观或只有在他们这样做时才怪自己?

最佳答案

在处理纯函数时,最好坚持完全实现,而不是使用 null , require或异常抛出,对数据中的所有失败进行编码。类型如 OptionEither正是为了这个。它们都是 monad,因此您可以对它们使用“for”语法。

以下对您的代码的修改显示了一个总函数 apply ,当输入 Java URI 时,它只产生一个有意义的值不提供 null s。我们通过将结果包装在 Option 中来对“有意义”的概念进行编码。 .

object Url {
  def apply(uri: java.net.URI): Option[Url] =
    for {
      protocol <- Option(uri.getScheme)
      host <- Option(uri.getHost)
      path <- Option(uri.getRawPath)
    }
    yield Url(protocol, host, path)
}

case class Url(protocol: String, host: String, path: String)

函数Option是一个标准的空检查函数,它映射 nullNone并将值包装在 Some 中.

关于你的“设置”功能,你可以实现null - 类似地检查它们,使用 Option .例如。:
case class Url(protocol: String, host: String, path: String) {
  def protocol(value: String): Option[Url] = 
    Option(value).map(v => copy(protocol = v))
  // so on...
}

但是我会建议反对。在 Scala 中,通常不使用 null s,所以只实现 null 也是惯例。 -处理“桥接”API,当您从 Java 库中获取值时。这就是为什么null - 从 java.net.URI 转换时检查确实很有意义,但在那之后你就进入了 Scala 世界,那里应该没有 null s,因此 null -检查只是变得多余。

关于scala - 在 Scala 中进行空检查的最佳实践,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23992051/

相关文章:

scala - Spark Map 列中最大值对应的键

scala - 使用 deb 文件和 SBT 为生产设置日志记录/配置

Scala 在枚举上匹配 int

validation - 通过 for-comprehension 线程 `Try` s

performance - 为什么电梯框架这么慢?

scala - Akka scala-io 询问并等待响应

java - 如何在 Play 框架中的 Action 中获取调用的 Action 的响应

Scala 组合函数

scala - 为什么zio的putStrLn没有输出

java - Scala 泛型混淆