在Scala中进行空值检查的最佳做法
我明白,在
Scala中,null被皱眉,而且应该总是包含一个Option中的可选值(如果有的话可以使用“null”类型).
优点是明确的,不应该需要检查空值,结果代码更安全,更愉快阅读. 然而,实际上,没有什么可以阻止一个值为null – 该规则不是由编译器执行的,更是一个绅士的协议.例如,当与Java API进行交互时,这可能会很容易中断. 这是最好的做法吗?比方说,我需要编写一个Url案例类,并且可以从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实例可以为getScheme,getHost和getRawPath返回null.在apply(URI)方法(例如require语句)中,是否足以防范这些问题?在技??术上,为了完全安全,最好保护协议,主机和路径助手方法以及构造函数,但这听起来像是大量的工作和样板. 它是否被认为是安全的,而不是保护API已知接受/返回空值(在我们的示例中为URI),并假设外部调用者将不会传递空值或者只有自己负责? 解决方法
在处理纯函数时,总是更好地坚持总体实现,而不是使用null,require或exception throwing来对数据中的所有故障进行编码.类似于Option和Either的都是这样的.他们都是单子,所以你可以使用“for”的功能.
对代码的以下修改显示了一个总功能应用,当输入的Java URI不提供空值时,该函数只产生一个有意义的值.我们通过将结果包装在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,path: String) 函数Option是一个标准的空值检查函数,它将null映射为None,并在Some中包装值. 关于您的“设置”功能,您可以使用Option来实现空检.例如.: case class Url(protocol: String,path: String) { def protocol(value: String): Option[Url] = Option(value).map(v => copy(protocol = v)) // so on... } 不过我会反对的.在Scala中,通常不要使用null,因此当您从Java库获取值时,通常只能对“bridge”API执行空处理.这就是为什么在从java.net.URI转换时,空值检查确实是完美的,但之后,您在Scala世界中不应该有空值,因此空值检查简单地变得冗余. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |