【发布时间】:2011-05-16 12:17:58
【问题描述】:
给定:
case class Foo(a: Int, b: String, c: Double)
你可以说:
val params = Foo(1, "bar", 3.14).productIterator.toList
然后得到:
params: List[Any] = List(1, bar, 3.14)
有没有办法“倒退”并直接从这个列表中重新创建一个 Foo 对象,即:
Foo.createFromList(params) // hypothetical
而不是写:
Foo(params(0).asInstanceOf[Int], params(1).asInstanceOf[String], params(2).asInstanceOf[Double])
编辑:似乎可以归结为能够将列表的元素作为参数发送给函数,而无需明确写出它们,例如:
def bar(a: Int, b: Int, c: Int) = //...
val list = List(1, 2, 3, 4, 5)
bar(list.take(3)) // hypothetical, instead of:
bar(list(0), list(1), list(2))
我希望能够做到:
bar(list.take(3): _*)
但这似乎不起作用。
编辑:基于即兴答案的解决方案,但直接调用构造函数而不是使用 apply 方法:
case class Foo(a: Int = 0, b: String = "bar", c: Double = 3.14) {
val cs = this.getClass.getConstructors
def createFromList(params: List[Any]) =
cs(0).newInstance(params map { _.asInstanceOf[AnyRef] } : _*).asInstanceOf[Foo]
}
现在你可以这样做了:
scala> Foo().createFromList(List(4, "foo", 9.81))
res13: Foo = Foo(4,foo,9.81)
您也可以将创建方法重构为 trait:
trait Creatable[T <: Creatable[T]] {
val cs = this.getClass.getConstructors
def createFromList(params: List[Any]) =
cs(0).newInstance(params map { _.asInstanceOf[AnyRef] } : _*).asInstanceOf[T]
}
case class Bar(a: Int = 0, b: String = "bar", c: Double = 3.14) extends Creatable[Bar]
然后做例如:
scala> val bar = Bar()
bar: Bar = Bar(0,bar,3.14)
scala> bar == bar.createFromList(bar.productIterator.toList)
res11: Boolean = true
【问题讨论】:
-
做一些快速基准测试,您会发现只需手动粘贴所有值,例如Foo(list(0), list(1), list(2)) 它快 10 倍。测试一个有 43 个值的案例类。
标签: scala