有两个案例类,它们非常相似:
case class A(aaa:String, bbb:String, ccc:String, ddd:String)
case class B(aaa:String, bbb:String, ccc:String, ddd:String, eee:String)
说我有一个
A
类的实例:val a = A("111","222","333","444")
有什么方法可以快速创建基于
B
的A
类的实例吗?我现在可以这样做(IMO不太好):
val b = B(a.aaa, a.bbb, a.ccc, a.ddd, "some-eee")
最佳答案
这对于Shapeless 2.0非常简单(您可以在Shapeless 1.2.4中完成,但是会有一些样板):
scala> import shapeless._, syntax.std.product._
import shapeless._
import syntax.std.product._
scala> val b = Generic[B] from a.productElements :+ "some-eee"
b: B = B(111,222,333,444,some-eee)
然后朝相反的方向:
scala> val c = Generic[A] from b.productElements.init
c: A = A(111,222,333,444)
这种方法不会确保名称对齐,但是如果您输入的类型错误,则会抱怨。当然也可以使用此方法进行更复杂的转换,尽管可能会有些混乱。例如,假设我们要在参数列表的中间添加一个元素:
case class B(aaa: String, bbb: String, eee: String, ccc: String, ddd: String)
我们需要编写如下内容:
val b = Generic[B].from(
(a.productElements.take[Nat._2] :+ "some-eee") ++
a.productElements.drop[Nat._2]
)
仍然不是那么可怕。
如果您无法使用Shapeless之类的东西,那么您当前的解决方案将达到和获得的最佳效果。