我正在尝试编写一个样板函数,该函数可以接受一对通用案例类对象,并在其val
集合上执行一些操作,然后返回案例类的新实例。
在更详细的层面上,这不是本问题的预期焦点,我正在执行的操作是压缩两个两个val列表,并通过List选择性地决定将哪个元组项放入新实例中[Boolean]表示左对象或右对象的标志。
我已经编写了大部分概念,并且到目前为止我的研究工作最好的策略是将case类对象转换为vals列表(使用Product.productIterator)然后最终转换为将val转换为元组(SO reference)以提供给Function.tupled(SO reference)(在案例类中可用)。
trait PermissionMask[B <: Product] {
val permissionMask: List[Boolean]
def mergePermissibleEdits(userObject: B, trustedObject: B) = {
val possibleValues = (userObject.productIterator.toList) zip (trustedObject.productIterator.toList)
val valuesWithFlags = possibleValues zip permissionMask
val mergedObjectList = valuesWithFlags map { case ((userValue, trustedValue), userEditable) => if (userEditable) userValue else trustedValue }
//TODO: Not possible, I don't have a direct reference to the case class since it's generic, not sure how to get the reference
B.tupled(mergedObjectList) //I have implicit conversions to tuple1-22 from list
}
}
如果我没有使用泛型并且知道具体的case类,我可以简单地调用SomeCaseClass.tupled(mergedObjectList)。然而,由于它是通用的,我对如何(如果可能的话)我可以进行相同的调用模糊不清。
答案 0 :(得分:2)
如上所述,您无法使用tupled
,因为它不适用于所有案例类apply
方法。这是一个相当hacky的版本,但可行的&#39;可以&#39;工作。这将获取第一个构造函数并将合并的参数列表应用于它。 警告,这非常可疑且非常容易破碎,我不会在生产中使用它:
def mergePermissibleEdits[B <: Product : ClassTag](userObject: B, trustedObject: B, permissionMask: List[Boolean]) = {
val possibleValues = userObject.productIterator.toList.map(_.asInstanceOf[AnyRef]) zip trustedObject.productIterator.toList.map(_.asInstanceOf[AnyRef])
val valuesWithFlags = possibleValues zip permissionMask
val mergedObjectList = valuesWithFlags map { case ((userValue, trustedValue), userEditable) => if (userEditable) userValue else trustedValue}
implicitly[ClassTag[B]].runtimeClass.getConstructors.head.newInstance(mergedObjectList: _*).asInstanceOf[B]
}
case class Id(id1: Int, id2: String, id3: Double)
println(mergePermissibleEdits(Id(1, "test", 3.0), Id(4, "works", 6.0), List(true, false, true)))
//prints Id(1,works,3.0)