2012-03-15 69 views
23

我有这样的方法:斯卡拉默认参数和空

def aMethod(param: String = "asdf") = { 
    ... 
} 

如果调用该方法如下,那么参数是给定的默认值“ASDF”:

aMethod() ... 

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

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

在Scala中做这件事最好的方法是什么?我可以考虑模式匹配或简单的if声明。

回答

46

模式匹配

def aMethod(param: String = null) { 
    val paramOrDefault = param match { 
     case null => "asdf" 
     case s => s 
    } 
} 

选项(隐含的)

def aMethod(param: String = null) { 
    val paramOrDefault = Option(param).getOrElse("asdf") 
} 

选项(明确)

def aMethod(param: Option[String] = None) { 
    val paramOrDefault = param getOrElse "asdf" 
} 

最后一种方法实际上是最习惯和可读性,一旦你使用到它。

+1

有没有办法隐式转换为选项?当然,我可以写自己的def,但API中是否有一个? – 2012-03-15 20:32:37

+4

@JohnSmith:你的意思是这样的:'implicit def obj2Option [T](t:T)= Option(t)'?我认为,作为标准隐式转换的一部分,这太脆弱/危险了,我不知道这样做。 – 2012-03-15 20:38:01

+0

@TomaszNurkiewicz请看我的回答,因为这个解决方案在仔细检查后会对Scala开发工具产生负面影响,并且在涉及继承时可能会破坏代码。 – 2012-03-15 23:17:48

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

    println(p) 
} 

但是这个问题必须问:为什么允许nullOption可能在你的情况下?为此,你可以这样做:

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

这表明你的方法期望有一个“空”参数的可能性。

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 
} 

有一些好处:

  • 的方法定义清楚地表明该参数的缺省值。
  • 正确的默认值可以通过Scala工具选取,包括ScalaDoc。
  • 没有必要定义一个额外的值来代替方法体内的原始参数 - 更少的错误空间,更容易推理。
  • 该模式相当简洁。

此外,考虑以下情形:

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

class AClass extends ATrait { 
    .... 
} 

显然,在这里,我们需要延长的特点,同时保留原来的默认值。任何涉及最初将参数设置为null跟着一个校验和实际的默认值将打破由特质合同成立的模式:

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

事实上,在这种情况下,以保护从ATrait原始值的唯一途径将是:

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

然而,当有可以设置为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 
} 

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

+0

有什么优势吗?我真的很喜欢你的方法(和理由);我希望能给它更多的观点;因为我认为它应该是答案。谢谢。 – Neil 2016-02-26 23:02:37