假设我们有一个类构造函数,它接受具有默认值的参数。
class A(val p1 : Int = 3, val p2 : Int = 4)
假设我无法控制此类,无论如何都无法修改它。我想要做的是调用A的构造函数,其中p1 = 5,p2 =(如果condition1 == true则为5,否则为默认值)。一种方法是
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类中的字段是val,因此在实例化A之后我无法更改它们。
答案 0 :(得分:1)
在我看来,你有三种可能性:
创建变量以保存您要指定的每个值,执行所有代码以填充值,并在结尾处实例化A
一次。这需要知道默认值,如Ionut所述。我不认为创建一个抛弃对象来读取默认值就是那些hackish - 当然不如嵌入默认值那么多 - 但无论如何。
使用反射API创建A
。我不确定如何做到这一点但几乎可以肯定你可以传入一个参数列表,任何未指定的参数都是默认的。这需要Scala 2.10;在此之前,只有Java反射API可用,你必须破解可选参数的内部实现, hackish。
使用宏。也是2.10+。我认为quasiquotes应该可以毫不费力地做到这一点,虽然我不太熟悉它们所以我不能肯定地说。
答案 1 :(得分:1)
获取默认值
val defaultA = new A()
然后
val x = new A(p1 = 5, p2 = if (cond) 5 else defaultA.p2)
答案 2 :(得分: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。
答案 3 :(得分:0)
如何从A获得派生类:
class D(val t2: (Boolean, Int)) extends A {
override val p2: Int = if(t2._1) t2._2 else A.init$default$2
}
现在您可以像这样实例化A:
x = new D((condition1, 5))
如果您有更多参数,则可以为每个参数添加类似的覆盖语句和元组参数。
答案 4 :(得分: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