首先从未定义trait
成员val
如果他们是为了在以后得以实施点。
trait UberSomething {
def name: String
}
// these maybe in different files
case class Something(name: String) extends UberSomething
case class SomethingOther(name: String) extends UberSomething
import shapeless._, ops.hlist.Align
另一种方法我在什么地方#2见过,所以道歉偷街头信誉,是使用Align
使得字段顺序也没有什么关系。
class Convert[Target] {
def apply[Source, HLS <: HList, HLT <: HList](s: Source)(implicit
// Convert the Source to an HList type
// include field names, e.g "labelled"
// Shapeless "generates" this using an implicit macro
// it looks at our type, extracts a list of (Name, Type) pairs
genS: LabelledGeneric.Aux[Source, HLS],
// Convert the Target o an HList type
// include field names, e.g "labelled"
// So again we have a (Name, Type) list of pairs this time for Target
genT: LabelledGeneric.Aux[Target, HLT],
// Use an implicit align to make sure the two HLists
// contain the same set of (Name, Type) pairs in arbitrary order.
align: Align[HLS, HLT]
) = genT from align(genS to s)
}
// Small trick to guarantee conversion only requires
// a single type argument, otherwise we'd have to put something
// in place for HLS and HLT, which are meant to be path dependant
// and "calculated" by the LabelledGeneric.Repr macro so it wouldn't work as it breaches the "Aux pattern", which exposes a type member materialized by a macro in this case.
// HLT and HLS come from within genS.Repr and genT.Repr.
def convert[T] = new Convert[T]
这是一个好一点的HList
PARAMS是很好的掩盖作为apply
一部分,所以你不要自己绊倒了。
val sample = Something("bla")
convert[SomethingOther](sample) // SomethingOther("bla")
我们来看看这一行:genT from align(genS to s)
。
首先genS to s
的Source
实例转换为LabelledGeneric
,e.g一个HList
与现场信息。
对齐为Source
类型创建的HList
的类型和字段以匹配Target
类型。
genT from ..
允许我们从授予的编译器可以“证明”的字段和类型为“所有有”一个HList
,这是我们已经有了Align
创建Target
一个实例。
无形绝对可以做到这一点,看看http://stackoverflow.com/questions/23192760/safely-copying-fields-between-case-classes-of-different-types –
谢谢,这看起来很有希望 – Sofia