2013-10-17 34 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) 
相关问题