Scala对';元组';从case类泛化
我正在尝试编写一个样板函数,它可以获取一对泛型case类对象,并对它们的Scala对';元组';从case类泛化,scala,Scala,我正在尝试编写一个样板函数,它可以获取一对泛型case类对象,并对它们的vals集执行一些操作,然后返回case类的一个新实例 在一个更详细的层次上,我正在执行的操作不是这个问题的重点,而是压缩两个VAL列表,并通过指示左或右对象的标记列表[Boolean]有选择地决定将元组的哪个项放入新实例中 我已经完成了大部分概念的编写,到目前为止,我的策略是将case类对象转换为一个vals列表(使用Product.productIterator),然后最终将一个vals列表转换为一个tuple(),以输
val
s集执行一些操作,然后返回case类的一个新实例
在一个更详细的层次上,我正在执行的操作不是这个问题的重点,而是压缩两个VAL列表,并通过指示左或右对象的标记列表[Boolean]有选择地决定将元组的哪个项放入新实例中
我已经完成了大部分概念的编写,到目前为止,我的策略是将case类对象转换为一个vals列表(使用Product.productIterator),然后最终将一个vals列表转换为一个tuple(),以输入Function.tuple()(在case类上可用)
trait PermissionMask[B if(userEditable)userValue else trustedValue}
//TODO:不可能,我没有直接引用case类,因为它是泛型的,不知道如何获取引用
B.tuple(mergedObjectList)//我有从列表到tuple1-22的隐式转换
}
}
如果我没有使用泛型并且知道具体的case类,我可以简单地调用SomeCaseClass.tuple(mergedObjectList)。但是,由于它是泛型的,所以我对如何调用(如果可能的话)不太清楚我可以做同样的调用。正如我上面所说的,你不能使用
tuple
,因为它不适用于所有的case类apply
方法。这是一个相当粗糙的版本,但可能“可以”工作。这需要第一个构造函数,并将合并的参数列表应用于它。警告,这是非常可疑和非常容易破坏的,我不会在生产中使用:
def mergepermissibleeditions[B如果(userEditable)userValue else trustedValue}
隐式[ClassTag[B]].runtimeClass.getConstructors.head.newInstance(mergedObjectList:*).asInstanceOf[B]
}
案例类Id(id1:Int,id2:String,id3:Double)
println(合并许可编辑(Id(1,“测试”,3.0),Id(4,“工作”,6.0),列表(真,假,真)))
//打印Id(1,工作,3.0)
一般来说,这类事情并不容易,很多工作都是在Shapeless中为您完成的。请注意,如果您的case类只有一个元素,那么apply
方法是Function1
,它没有tupled
函数,2+已经tupled。谢谢。您是否可以进一步说明您对使用该方法的关注是否主要基于易破坏性(例如,如果B、userObject或trustedObject的运行时类型不匹配似乎很难防止)或者还有其他问题吗?@Rich不能保证权限掩码
大小与可能值
的大小相同,而且这使用了它为B
找到的第一个构造函数,这可能不是合适的构造函数,它还将Any
强制转换为AnyRef
,这很可能是正确的,但是t如果你有一个AnyVal
,它就会坏掉。我理解你在这里想做什么,我认为不成形可能是一个更好的镜头使用方法(不是说我有一个很好的例子给你)或者直接合并您的案例类。感谢您的评论。AnyRef vs AnyVal是我没有考虑过的最令人担忧的问题。在更高的层次上,鉴于本课程和相关问题涉及的局限性,我可能最好停止强迫自己回到案例类。我的最终目标是equirements不依赖于它,天真只是让它看起来像一个好主意。我将研究Shapeless,即使我最终没有使用它。支持文档似乎有助于进一步了解Scala中的类型和泛型。作为参考,我发现这些文章阐明了泛型类型的潜在问题多态性涉及到我最初陈述的目标。第二部分似乎特别总结了一些相关的观察结果,并重新审视了Any
到AnyRef
的演员阵容,没有使用“AnyVal”(我假设你指的是地图(u.asInstanceOf[AnyRef])
),它真的会崩溃吗?您的示例在Id case类中有两个AnyVal(Int和Double),我可以确认它确实像您演示的那样工作。我是否误解了您的评论?
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
}
}
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)