gpt4 book ai didi

scala - 将 HashMap 键/值对映射到 Scala 中的命名构造函数参数

转载 作者:行者123 更新时间:2023-12-04 03:34:05 25 4
gpt4 key购买 nike

是否可以将 Map 的键值对映射到具有命名参数的 Scala 构造函数?

也就是说,给定

class Person(val firstname: String, val lastname: String) {
...
}

...我如何使用类似的 map 创建 Person 的实例

val args = Map("firstname" -> "John", "lastname" -> "Doe", "ignored" -> "value")

我最终想要实现的是映射 Node4J Node 的好方法对象到 Scala 值对象。

最佳答案

这里的关键见解是构造函数参数名称是可用的,因为它们是构造函数创建的字段的名称。所以前提是构造函数不对其参数执行任何操作,而是将它们分配给字段 ,然后我们可以忽略它并直接使用字段。

我们可以用:

def setFields[A](o : A, values: Map[String, Any]): A = {
for ((name, value) <- values) setField(o, name, value)
o
}

def setField(o: Any, fieldName: String, fieldValue: Any) {
// TODO - look up the class hierarchy for superclass fields
o.getClass.getDeclaredFields.find( _.getName == fieldName) match {
case Some(field) => {
field.setAccessible(true)
field.set(o, fieldValue)
}
case None =>
throw new IllegalArgumentException("No field named " + fieldName)
}

我们可以调用一个空白的人:
test("test setFields") {
val p = setFields(new Person(null, null, -1), Map("firstname" -> "Duncan", "lastname" -> "McGregor", "age" -> 44))
p.firstname should be ("Duncan")
p.lastname should be ("McGregor")
p.age should be (44)
}

当然,我们可以通过一点拉皮条做得更好:
implicit def any2WithFields[A](o: A) = new AnyRef {
def withFields(values: Map[String, Any]): A = setFields(o, values)
def withFields(values: Pair[String, Any]*): A = withFields(Map(values :_*))
}

这样您就可以调用:
new Person(null, null, -1).withFields("firstname" -> "Duncan", "lastname" -> "McGregor", "age" -> 44)

如果必须调用构造函数很烦人,Objenesis 可以让您忽略缺少无参数构造函数:
val objensis = new ObjenesisStd 

def create[A](implicit m: scala.reflect.Manifest[A]): A =
objensis.newInstance(m.erasure).asInstanceOf[A]

现在我们可以把两者结合起来写
create[Person].withFields("firstname" -> "Duncan", "lastname" -> "McGregor", "age" -> 44)

关于scala - 将 HashMap 键/值对映射到 Scala 中的命名构造函数参数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7455681/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com