考虑到我们有一个对象集合,它们都是case类,并且它们都有一个字段,比如一个uuid,我们想要收集它们以供进一步使用。在我的特定情况下,对象来自四个不同数据库表的行。在其他情况下,它们可能来自某个异构容器,或者来自管道或其他任何东西。
使用java的内省混合我可以在一个笔划中读取所有uuids,如
val LocalTables=Seq(t1,t2,t3,t4)
for (t <- LocalTables) {
t foreach ( v => {
val metodo=v.getClass.getDeclaredMethod("id")
println(metodo.invoke(v))
}
}
但我觉得很脏。有没有办法告诉scala去直接访问v.id?
这个具体的用例是用于数据库访问,因此可以通过特定查询轻松解决。但问题更为笼统,我想了解可以使用哪些工具在某些异构值集合上运行 foreach 。
答案 0 :(得分:3)
在精确/安全和简单/灵活性之间存在各种选择。很多logic for Haskell适用。想到的选项是:
非常容易使用,或多或少安全,即使它们最终编译为反射:
val localTables = Seq[{def id: UUID}](t1, t2, t3, t4)
localTables foreach {t => println(t.id)}
非常安全,但要求您修改类型:
trait HasId { def id: UUID }
case class Something(id: UUID, ...) extends HasId
val localTables = Seq[HasId](...)
...
HList
和poly
安全灵活,但有点吓人
import shapeless._, hlist._, poly._
object extractId extends Poly1 {
implicit val caseFoo = at[Foo](_.id)
implicit val caseBar = at[Bar](_.id)
...
}
val localTables = t1 :: t2 :: ... :: HNil // of type Foo :: Bar :: ... :: HNil
val ids: List[UUID] = localTables map extractId toList
ids foreach println