2012-03-15 101 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