Scala默认参数为null

Joh*_*ith 29 scala

我有这样的方法:

def aMethod(param: String = "asdf") = {
    ...
}
Run Code Online (Sandbox Code Playgroud)

如果调用该方法如下,那么param将被赋予默认值"asdf":

aMethod() ...
Run Code Online (Sandbox Code Playgroud)

但我想要的是,如果调用该方法null,那么也将应用默认值:

aMethod(null)  //inside the method, I can use `param` and it has the value "asdf".
Run Code Online (Sandbox Code Playgroud)

什么是Scala最好的方法?我可以想到模式匹配或简单的if陈述.

Tom*_*icz 52

模式匹配

def aMethod(param: String = null) {
    val paramOrDefault = param match {
        case null => "asdf"
        case s => s
    }
}
Run Code Online (Sandbox Code Playgroud)

选项(含蓄)

def aMethod(param: String = null) {
    val paramOrDefault = Option(param).getOrElse("asdf")
}
Run Code Online (Sandbox Code Playgroud)

选项(明确)

def aMethod(param: Option[String] = None) {
    val paramOrDefault = param getOrElse "asdf"
}
Run Code Online (Sandbox Code Playgroud)

一旦你习惯了,最后一种方法实际上是最惯用和可读的.

  • @JohnSmith:你的意思是:`隐式def obj2Option [T](t:T)= Option(t)`?我认为这是标准的隐式转换的一部分太脆弱/危险,我不知道这些. (4认同)

dhg*_*dhg 5

def aMethod(param: String = null) = { 
  val p = 
    if(param == null)
      "asdf"
     else
       param

  println(p) 
}
Run Code Online (Sandbox Code Playgroud)

但必须提出这样的问题:为什么要允许null?将Option你的情况可能吗?为此您可以这样做:

def aMethod(param: Option[String]) = { 
  val p = param.getOrElse("asdf")    
  println(p)
}
Run Code Online (Sandbox Code Playgroud)

这清楚表明您的方法期望"null"参数的可能性.


Vla*_*dim 5

如果该方法只有一个或两个默认参数可以设置为null考虑此模式:

// please note that you must specify function return type
def aMethod (x:String = "asdf"):String = if (x==null) aMethod() else {
    // aMethod body ...
    x 
}
Run Code Online (Sandbox Code Playgroud)

有一些好处:

  • 方法定义清楚地指示参数的默认值.
  • Scala工具可以选择正确的默认值,包括ScalaDoc.
  • 没有必要定义一个额外的值来替换方法体内的原始参数 - 更少的错误空间,更容易推理.
  • 模式相当简洁.

此外,请考虑以下情形:

trait ATrait {
  def aMethod (x:String = "trait's default value for x"):String
}

class AClass extends ATrait {
    ....
}
Run Code Online (Sandbox Code Playgroud)

显然,这里我们需要扩展特征,同时保留原始默认值.最初设置参数null后跟检查和实际默认值的任何模式都将破坏特征建立的合同:

class AClass extends ATrait {
  // wrong, breaks the expected contract
  def aMethod(x: String = null):String = {
      val xVal = if (x == null) "asdf" else x 
      ...
  }
}
Run Code Online (Sandbox Code Playgroud)

实际上,在这种情况下,保留原始值的唯一方法ATrait是:

class AClass extends ATrait {
  override def aMethod (x:String):String = if (x==null) aMethod() else {
    ... // x contains default value defined within ATrait
  }
}
Run Code Online (Sandbox Code Playgroud)

但是,在有多个或两个默认参数可以设置为null模式的情况下,开始变得相当混乱:

// two parameters
def aMethod (x:String = "Hello",y:String = "World"):String = 
  if (x==null) aMethod(y=y) else
  if (y==null) aMethod(x=x) else {
    // aMethod body ...
    x + " " + y
}

// three parameters
def aMethod (x:String = "Hello",y:String = " ",z:String = "World"):String = 
  if (x==null) aMethod(y=y,z=z) else
  if (y==null) aMethod(x=x,z=z) else 
  if (z==null) aMethod(x=x,y=y) else {
    // aMethod body ...
    x + y + z
}
Run Code Online (Sandbox Code Playgroud)

仍然在覆盖现有合同时,这可能是兑现原始默认值的唯一方法.