如何基于另一个类似的case class创建一个case class?

4

有两个案例类,它们非常相似:

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")

有没有一种快速创建基于 A 的类 B 实例的方法?

我现在可以像这样做(在我看来不太好):

val b = B(a.aaa, a.bbb, a.ccc, a.ddd, "some-eee")
1个回答

4

使用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这样的东西,那么你当前的解决方案已经达到了最好的水平。


1
如果类B被定义为case class B(aaa:String, bbb:String, eee:String, ccc:String, ddd:String),那么如果eee在中间呢? - Freewind

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接