首先從未定義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