Scala:将通用案例 class 复制到另一个

Scala: Copying a generic case class into another

我有以下设置,我想将 baseData 的实例复制到 moreData 的实例中:

sealed trait baseData {
  def weight: Int
  def priority: Int
} 

sealed trait moreData {
  def weight: Int
  def priority: Int
  def t: String
  def id: String
} 

case class data1(override val weight: Int, override val priority: Int) extends baseData 
case class moreData1 (override val weight:Int, override val priority: Int, override val t: String, override val id: String)extends moreData

所以将myData复制到下面的otherData中:

val myData = data1(1,1) 
val otherData = moreData1 (2,2,"C","abcd") 

会产生:moreData1(1,1,"C","abcd").

为此,我想使用具有以下签名的函数,因为我会有不止一种情况 class 扩展 baseDatamoreData:

def copyOver[A <:baseData, B <:moreData](from: A, to: B) = {} 

我相信您可以使用 Shapeless, but haven't figured out how. There are examples (here) on copying case classes extending a same trait, and others (here) 通过通用表示在不同大小写 class 之间映射值来做到这一点。但是我还没有弄清楚如何将 LabelledGeneric 与传递给 copyOver 的特征边界参数一起使用。我也不想对 otherDatamyData 中不存在的额外字段进行硬编码。

我正在寻找一个完全通用的实现。有什么想法吗?

您应该可以使用 your first shapeless example 中的 UpdateRepr 类型 class。

您可以使用 UpdateRepr 定义 copyOver,如下所示:

import shapeless._

// baseData, moreData, data1, moreData1
// UpdateRepr ...

def copyOver[A <: baseData, B <: moreData, R <: HList](
  from: A,
  to: B
)(implicit 
  lgen: LabelledGeneric.Aux[A, R],
  update: UpdateRepr[B, R]
): B = update(to, lgen.to(from))

您可以按如下方式使用:

val myData = data1(1,1) 
val otherData = moreData1(2,2,"C","abcd") 

copyOver(myData, otherData)
// moreData1 = moreData1(1,1,C,abcd)

请注意,您可能 运行 遇到 SI-7046 的问题,因为 UpdateRepr 的密封特征(Coproduct)类型 class 派生,您可以在REPL 或拆分 UpdateRepr 和多个文件的密封特征。