2017-03-07 33 views
4

是否有可能使用无形转换1对象到另一个对象,而如何使用不成形从一个类复制场到另一个不同的类

  • 做一些细微的变换就像转换选项[T]到T (无手动定义映射用于每个类别)

  • 忽略丢失的字段

进口shapeless._ 进口shapeless.syntax._

case class Cat(color: Option[Int], isFat: Boolean, newField: String) 
case class Kitten(color: Int, isFat: Boolean) 

val kitten = Kitten(2, true) 

val genCat = Generic[Cat] 
val genKit = Generic[Kitten] 

val cat: Cat = genCat.from(genKit.to(kitten)) 

这失败,出现以下错误
(其扩展到)shapeless.::[Int,shapeless.::[Boolean,shapeless.HNil]

回答

0

这是一个使用与我的previous answer相同的想法的解决方案。

  • 做次要转换(选项为默认值)
  • 忽略尾字段

当然也有一定的限制。

object HListsFlatten { 

    import shapeless.{::, HList, HNil} 

    sealed trait DefaultValue[V] { 
    def value: V 
    } 

    implicit val defaultInt: DefaultValue[Int] = new DefaultValue[Int] { 
    override def value = 0 
    } 

    sealed trait HConv[From <: HList, To <: HList] { 
    def convert(list: From): To 
    } 

    implicit def buildHConvNil: HConv[HNil, HNil] = new HConv[HNil, HNil] { 
    override def convert(list: HNil): HNil = HNil 
    } 

    implicit def buildHConvShorten[H <: AnyVal, T <: HList] 
    : HConv[::[H, T], ::[H, HNil]] = new HConv[::[H, T], ::[H, HNil]] { 
    override def convert(list: ::[H, T]): ::[H, HNil] = { 
     list.head :: HNil 
    } 
    } 

    implicit def buildHConvOption[H, T <: HList, T2 <: HList](
     implicit conv: HConv[T, T2], 
     default: DefaultValue[H]): HConv[::[Option[H], T], ::[H, T2]] = 
    new HConv[::[Option[H], T], ::[H, T2]] { 
     override def convert(list: ::[Option[H], T]): ::[H, T2] = { 
     list.head.getOrElse(default.value) :: conv.convert(list.tail) 
     } 
    } 

    implicit def buildHConv[H <: AnyVal, T <: HList, T2 <: HList](
     implicit conv: HConv[T, T2]): HConv[::[H, T], ::[H, T2]] = 
    new HConv[::[H, T], ::[H, T2]] { 
     override def convert(list: ::[H, T]): ::[H, T2] = { 
     list.head :: conv.convert(list.tail) 
     } 
    } 

    implicit def buildHConvString[T <: HList, T2 <: HList](
     implicit conv: HConv[T, T2]): HConv[::[String, T], ::[String, T2]] = 
    new HConv[::[String, T], ::[String, T2]] { 
     override def convert(list: ::[String, T]): ::[String, T2] = { 
     list.head :: conv.convert(list.tail) 
     } 
    } 

    def flatten[A <: HList, B <: HList](list: A)(implicit conv: HConv[A, B]): B = 
    conv.convert(list) 

} 

实施例:

import shapeless.Generic 

case class Cat(color: Option[Int], isFat: Boolean, newField: String) 
case class Kitten(color: Int, isFat: Boolean) 

val cat = Cat(color = Some(3), isFat = true, "SomeValue") 

val genCat = Generic[Cat] 
val genKit = Generic[Kitten] 

import HListsFlatten._ 

scala> val kitten = genKit.from(flatten(genCat.to(cat))) 
kitten: Kitten = Kitten(3,true) 
相关问题