在我的项目中,有很多地方的对象是从集合中挑选出来的,在更改了一些值的情况下进行复制,然后推回到集合中。我一直在尝试创建自己的"复制"方法,除了进行复制外,还为我提供了一个"Diff"对象。换句话说,包含你刚刚放入其中的论点的东西。
然后应该将"Diff"对象发送到某个地方进行聚合,这样其他人就可以获得自上次以来的所有更改的报告,而无需发送实际的整个对象。如果一个人这样做,这一切都很简单:
val user = new User(Some(23), true, "arne", None, None, "position", List(), "email", None, false)
val user0 = user.copy(position = "position2")
list ::= user0
val diff = new Diff[User](Map("position" -> "position2"))
然而,那里有一些重复的工作,我非常希望只使用一种方法,比如:
val (user, diff) = user.copyAndDiff(position = "position")
我还没能弄清楚"复制"的参数实际采用的形式,但我也可以使用其他形式。
我做了一个带有Type参数的方法,它应该是一个副本和一个diff
object DiffCopy[Copyable]{
def apply(original:Copyable, changes:Map[String, Any]){
original.copy(??uhm..
original.getAllTheFieldsAndCopyAndOverWriteSomeAccordingToChanges??
我的第一个问题是,似乎没有任何方法可以保证原始对象有一个可以重载的"复制"方法。当我想在新的复制对象中实际将更改分配给它们的正确字段时,就会出现第二个问题。我试着摆弄Reflection,并试图找到一种方法来设置名称为String的字段的值。在这种情况下,我可以将Diff作为一个简单的映射,只需首先创建这个Diff映射,然后将其应用于我的对象,并将它们发送到需要的地方。
然而,我最终在兔子洞里越陷越深,离我真正想要的越来越远。我得到了一个点,我有一个来自任意对象的字段数组,可以按名称获取它们,但我无法使它适用于泛型类型。所以现在我在这里问是否有人能就这种情况给我一些建议?
我能得到的最好的答案是,如果有人能告诉我一个简单的方法,将Map[String,Any]应用于等效于"复制"方法的东西。我很确定这应该可以实现,但目前我还无法实现…
有点过于复杂,但可以解决最初的问题。
我能得到的最好的答案是,如果有人能告诉我一个简单的方法,将Map[String,Any]应用于等效于"复制"方法的东西。我很确定这应该是可能实现的,但它只是目前超出了我的能力…
-
将case类中的所有字段都映射到映射中。
-
使用新值更新地图。
-
从新字段映射创建案例类。
问题:
- 低性能
我确信它可以做得更简单。。。
case class Person(name: String, age: Int)
def getCCParams(cc: Any) =
(Map[String, Any]() /: cc.getClass.getDeclaredFields) {(a, f) =>
f.setAccessible(true)
a + (f.getName -> f.get(cc))
}
def enrichCaseClass[T](cc: T, vals : Map[String, Any])(implicit cmf : ClassManifest[T]) = {
val ctor = cmf.erasure.getConstructors().head
val params = getCCParams(cc.asInstanceOf[Any]) ++ vals
val args = cmf.erasure.getDeclaredFields().map( f => params(f.getName).asInstanceOf[Object] )
ctor.newInstance(args : _*).asInstanceOf[T]
}
val j = Person("Jack", 15)
enrichCaseClass(j, Map("age" -> 18))