Scala动态实例化带有默认参数

20 浏览
0 Comments

Scala动态实例化带有默认参数

有没有一种方法可以动态实例化一个Scala case类,并指定一个或多个默认参数?

我正在寻找动态(基于反射)等效的方法:

case class Foo( name:String, age:Int = 21 )
val z = Foo("John") 

目前,如果我尝试这样做,我会得到一个异常:

val const = Class.forName("Foo").getConstructors()(0)
val args = Array("John").asInstanceOf[Array[AnyRef]]
const.newInstance(args:_*)

如果在参数数组中添加age的值,就没有问题。

0
0 Comments

Scala动态实例化默认参数的问题是由于反射机制导致的。在编译时,编译器会为调用中缺少参数的情况下提供默认值。但是反射机制并不支持默认参数。可以通过运行时方法获取默认值。那么问题来了,如何在没有实例化对象的情况下获取默认值呢?在这种情况下,可以使用伴生对象。

伴生对象是指与类名相同且被定义在同一个源文件中的对象。在伴生对象中,可以定义一些与类相关的静态方法和成员变量。通过伴生对象,可以在没有实例化对象的情况下访问类的默认参数。

解决方法如下:

class MyClass(param1: Int = 0, param2: String = "default") {
  def myMethod(): Unit = {
    println(s"param1: $param1, param2: $param2")
  }
}
object MyClass {
  def getDefaultParam1: Int = new MyClass().param1
  def getDefaultParam2: String = new MyClass().param2
}
// 使用伴生对象获取默认参数
val defaultParam1 = MyClass.getDefaultParam1
val defaultParam2 = MyClass.getDefaultParam2
val myObject = new MyClass()
myObject.myMethod()

在这个例子中,MyClass类有两个默认参数param1和param2。在伴生对象中,我们定义了两个方法getDefaultParam1和getDefaultParam2,分别返回默认参数param1和param2的值。通过调用这两个方法,我们可以在没有实例化对象的情况下获取默认参数的值。

最后,我们可以通过实例化MyClass类并调用其方法来验证获取的默认参数值是否正确。

0
0 Comments

Scala动态实例化带有默认参数的问题的出现是因为在运行时,可以将默认参数作为对象的方法来获取。在构造函数参数的情况下,可以使用伴生对象方法(scala 2.9.3)来获取默认参数。

$ echo 'class Test(t: Int = 666)' > test.scala
$ scalac -Xprint:typer test.scala
...
 def init$default$1: Int .annotation.unchecked.uncheckedVariance = 666

但是不能依赖于该方法的名称(scala 2.10.1):

scala> Test.$lessinit$greater$default$1
res0: Int = 666

我不知道如何获取构造函数的默认参数,但是在case class的情况下,可以获取到apply方法的默认参数。参见这个答案。

-snytt: 在2.9.3和2.10.1中,名称是不同的,所以不能使用名称,而是使用defaultGetterName来生成它。

-snytt: 你的评论让我想创建一个方法``。

0