Scala中的可选参数的模式使用null [英] Pattern for optional-parameters in Scala using null

查看:1017
本文介绍了Scala中的可选参数的模式使用null的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个函数,它接受可选参数。但是,这些不是Option [?],而是可以设置或null:

I have a function which takes optional parameters. However, these are not Option[?] but can be either set or null:

private def div(id: String = null, cssClass: String = null): JQuery = {
  val optId = Option(id)
  val optCssClass = Option(cssClass)
  ...
  // deal with optId and optCssClass using the Scala-way™
  ...
}



使用null,我知道应该避免像瘟疫。但是,它允许我编写如下代码:

I am using "null", which I know should be avoided like the plague. However, it allows me to write code like this:

div(id = "someId") // no cssClass
div(id = "otherId", cssClass = "someClass")

div(id = Some("someId")) // no cssClass
div(id = Some("otherId"), cssClass = Some("someClass"))

Scala模式? (使用null作为默认参数值并转换为Option)

Is this a known / acceptable Scala pattern? (using null as default parameter values and converting to Option)

还是仍然是heressy / bad-practice?如果是,为什么?

Or is it still heressy / bad-practice? If so, why?

推荐答案

这里的大多数答案都是提出一些null对象模式的变体,空字符串表示未定义(如 val optId = if(id.isEmpty)无其他一些(id)

Most of the answers here are proposing some variant of the "null object" pattern, by denoting an empty String to mean "undefined" (as in val optId = if(id.isEmpty) None else Some(id))

这里的catch是一个空字符串可能是一个有效的值!这是任何字符串,虽然你可以通过使用真的太可怕,可能涉及不可打印的字符缓解这个问题。例如:

The catch here is that an empty string might be a valid value! This is true of any String, though you can mitigate the problem by using something really outrageous, possibly involving non-printable characters. e.g:

val UndefinedString = "THIS-IS-A-REALLY-UNLIKELY-VALID-VALUE"

private def div(
  id: String = UndefinedString,
  cssClass: String = UndefinedString
): JQuery = {
  val optId = Option(id) filter (_ != UndefinedString )
  val optCssClass = Option(cssClass) filter (_ != UndefinedString )
  ...
  // deal with optId and optCssClass using the Scala-way™
  ...
}



更好的是,你可以使用不同的类型来表示你的空对象。因为你不能子类化 String ,你必须碰撞你的params到类型层次结构,并使它们 CharSequence s

Better still, you could use a different type to denote your null object. As you can't subclass String you'll have to bump your params up the type hierarchy and make them CharSequences

object NullCharSeq extends CharSequence {
  def charAt(idx: Int): Char = ???
  def length(): Int = 0
  def subSequence(start: Int, end: Int): CharSequence = this
  def toString(): String = ???
}

def charSeqToOptStr(cs: CharSequence): Option[String] = cs match {
  case NullCharSeq => None
  case x => Option(x) map (_.toString)
}

private def div(
  id: CharSequence = NullCharSeq,
  cssClass: CharSequence = NullCharSeq
): JQuery = {
  val optId = charSeqToOptStr(id)
  val optCssClass = charSeqToOptStr(cssClass)
  ...
  // deal with optId and optCssClass using the Scala-way™
  ...
}

这是一个重量级模式使用,但是如果你使用它很多( NullCharSeq charSeqToOptStr 只需要定义一次在代码库中)。

It's a heavyweight pattern for one-shot usage, but the cost is quickly amortized if you use it a lot (NullCharSeq and charSeqToOptStr only need to be defined once in the codebase).

也有零错误地传递你的未定义字符串的风险,因为它是一个有效的值。此外,您还可以直接接受CharBuffer / StringBuffer / StringBuilder作为参数。

There's also zero risk of mistakenly passing your "undefined" String as though it were a valid value. Plus, you gain the ability to directly accept CharBuffer/StringBuffer/StringBuilder as your arguments.

这篇关于Scala中的可选参数的模式使用null的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆