我试图将caseclassmerge示例从无形库修改为仅合并非空字段。
object mergeSyntax {
implicit class MergeSyntax[T](t: T) {
def merge[U](u: U)(implicit merge: CaseClassMerge[T, U]): T = merge(t, u)
}
}
trait CaseClassMerge[T, U] {
def apply(t: T, u: U): T
}
object CaseClassMerge {
import ops.record.Merger
def apply[T, U](implicit merge: CaseClassMerge[T, U]): CaseClassMerge[T, U] = merge
implicit def mkCCMerge[T, U, RT <: HList, RU <: HList]
(implicit
tgen: LabelledGeneric.Aux[T, RT],
ugen: LabelledGeneric.Aux[U, RU],
merger: Merger.Aux[RT, RU, RT]
): CaseClassMerge[T, U] =
new CaseClassMerge[T, U] {
def apply(t: T, u: U): T =
tgen.from(merger(tgen.to(t), ugen.to(u)))
}
}
如何修改合并逻辑,使第二个参数中的非空字段合并到第一个参数中?
答案 0 :(得分:1)
您可以将自己的隐式合并实现添加到当前作用域,覆盖标准合并:
object NotNullHListMerger {
import shapeless.labelled._
import shapeless.ops.record.Merger
import shapeless.ops.record.Remover
implicit def notNullHListMerger[K, V, T <: HList, M <: HList, MT <: HList]
(implicit
rm: Remover.Aux[M, K, (V, MT)],
mt: Merger[T, MT]
): Merger.Aux[FieldType[K, V] :: T, M, FieldType[K, V] :: mt.Out] =
new Merger[FieldType[K, V] :: T, M] {
type Out = FieldType[K, V] :: mt.Out
def apply(l: FieldType[K, V] :: T, m: M): Out = {
val (mv, mr) = rm(m)
val up = field[K](mv)
// Replace only if value is not null
val h = Option(up).getOrElse(l.head)
h :: mt(l.tail, mr)
}
}
}
import mergeSyntax._
import NotNullHListMerger._
case class Foo(i: Int, s: String, b: Boolean)
case class Bar(b: Boolean, s: String)
val foo = Foo(23, "foo", true)
val bar = Bar(false, null)
val merged = foo merge bar
assert(merged == Foo(23, "foo", false))