2017-03-07 4 views
4

別の別のクラスに一つのクラスからフィールドをコピーするには型崩れを使用するにはどのよう

  • はT にオプション[T]を変換するようないくつかのマイナーな変形をしながら別の1つのオブジェクトを変換するために、型崩れを使用することが可能です欠落フィールド

インポートshapeless._を無視

  • を(手動で各クラスのマッピングを定義しません)インポートこれは、次のエラーで失敗

    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.syntax._
    (展開に)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)