2013-10-17 42 views
9

假設我們有一個類構造函數,它接受具有默認值的參數。Scala可以選擇提供名爲默認參數

class A(val p1 : Int = 3, val p2 : Int = 4) 

比方說,我無法控制這個類,也無法修改它。我想要做的是調用A的構造函數p1 = 5,p2 =(如果condition1 == true,那麼5 else默認值)。要做到這一點的方法之一是

if(condition1) 
    x = new A(5,5) 
else 
    x = new A(5) 

正如你所看到的,這很容易得到大的,如果有很多參數,每次都必須有條件地供給。我想要的是類似

x = new A(p1 = 5, p2 = <if condition1 = true then 5 else default>) 

我該怎麼做?需要注意的是A類的字段是丘壑,所以實例A.

+0

創建一個不帶參數的一次性「A」是否很昂貴,以便您可以讀取其所有默認值並稍後在'if'表達式中使用它們? –

+0

我想過這個解決方案。它並不昂貴,但感覺有點冒險。如果可能,我想避免首先讀取默認參數。 – DSR

+0

查看http://docs.scala-lang.org/sips/completed/named-and-default-arguments.html上的最後一節「Default arguments」。看起來你可以調用方法來獲取默認值。順便說一句,如果你想出一些好東西,請回答你自己的問題! –

回答

1

在我看來,以後我不能改變他們,你有三種可能性:

  1. 創建變量來保存每個要的價值觀指定,執行所有代碼以填充值,並在末尾實例化A一次。正如Ionut所說,這需要知道默認值。我不認爲創建一個扔掉的對象來讀取默認值是一件駭人聽聞的事情 - 當然不像嵌入默認值那麼多 - 但無論如何。

  2. 使用反射API創建A。我不確定如何做到這一點,但幾乎可以肯定你可以傳入一個參數列表,並且可以指定任何未指定的參數。這需要Scala 2.10;在此之前,只有Java反射API可用,並且您必須通過內部實現的可選參數進行破解,其中

  3. 使用宏。還2.10+。我認爲quasiquotes應該能夠在沒有太多困難的情況下做到這一點,儘管我不太熟悉它們,所以我不能肯定地說。

0

這裏的快速排序的錯誤答案:

x = new A(p1 = 5, if (condition1) 5 else A.$lessinit$greater$default$2) 

「錯誤」的部分是,這部作品在2.10而不是2.9。默認方法的magick名稱已從版本更改爲版本(值得注意的是,在2.9和2.10之間),因此查找其名稱並通過反射調用它更爲安全。見Instantiating a case class with default args via reflection,How do I access default parameter values via Scala reflection?Scala dynamic instantiation with default arguments

0

怎麼樣從有這樣一個派生類:

class D(val t2: (Boolean, Int)) extends A { 
    override val p2: Int = if(t2._1) t2._2 else A.init$default$2 
} 

現在你可以實例化一個像這樣的:

x = new D((condition1, 5)) 

如果您有更多的參數,那麼你可以添加一個類似的覆蓋語句和元組參數。

0

我不禁感覺你所要求的有點不合理。如前所述,應該可以使用宏。但通常如果你對提供的構造函數/工廠不滿意,那麼你必須編寫自己的包裝器/工廠。就我個人而言,我認爲我們可能希望在整個默認值,Null對象和Option類中重新審視一下。但是可以在不使用宏的情況下剪切樣板文件。把一個隱含的布爾在實用軟件包:

implicit class BooleanRich2(n : Boolean) { 
    def apply[T](v1: T, v2: T): T = if (n) v1 else v2 
} 

然後說,我們希望使用下面的類,我們不能修改:

final class A(val p1: Int = 1, val p2: Int = 2, val p3: Int = 3, val p4: Int = 4){ 
    override def toString = s"p1: $p1, p2: $p2, p3: $p3, p4: $p4" 
} 

我們可以按如下方式使用它:

var c1 = true 
var c2 = false 
def c3(s: String) = (s =="") 

val a = new A(c1(20, 1)) //p1: 20, p2: 2, p3: 3, p4: 4 
println(a) //p1: 20, p2: 2, p3: 3, p4: 4 

val b = new A(p3 = c2(20, 3), p4 = c3("")(20, 4)) 
println(b) //p1: 1, p2: 2, p3: 3, p4: 20 

val c = new A(p3 = c1(20, 3), p4 = c3("A non empty String")(20, 4)) 
println(c) //p1: 1, p2: 2, p3: 20, p4: 4 
1

取默認值,

val defaultA = new A() 

Then

val x = new A(p1 = 5, p2 = if (cond) 5 else defaultA.p2) 
相關問題