如何将父对象解构后传入扩展子类的构造函数(Scala样例类场景)
Scala 复用 case class 属性构造新实例的实现方案
以下是几种常用实现方式,按复杂度从低到高排列:
方案1:直接手动取值(最通用,无额外依赖)
小场景下直接取已有实例的属性传入即可,语法最直观,没有额外性能开销:
case class Cat(name: String) case class PetPersian(name: String, price: Number) val c1 = Cat(name = "Meowth") val c2 = PetPersian( name = c1.name, price = 10000 )
方案2:用tupled方法结合Product特性(适合属性较多的场景)
case class 默认实现Product特质,可通过tupled方法将元组转换为构造函数入参:
// 先把Cat实例转成元组,拼接price参数后传入tupled方法 val c2 = PetPersian.tupled( (c1.name, 10000) ) // 如果属性很多不想逐个写,可动态拼接元组(Scala 2.13+ 原生支持) val c2 = PetPersian.tupled( Tuple.fromProduct(c1) :+ 10000 )
方案3:隐式扩展方法(高频转换场景调用更简洁)
如果经常需要做Cat到PetPersian的转换,可以定义扩展方法简化调用逻辑:
// 定义扩展方法 implicit class CatOps(cat: Cat) { def toPetPersian(price: Number): PetPersian = PetPersian(cat.name, price) } // 调用代码非常简洁 val c2 = c1.toPetPersian(10000)
方案4:Shapeless自动映射(重叠属性多的复杂场景)
如果两个case class重叠属性非常多,不想手动写属性映射,可以用Shapeless第三方库做自动字段匹配,不需要逐一声明属性对应关系:
import shapeless._ import syntax.singleton._ case class Cat(name: String) case class PetPersian(name: String, price: Number) val c1 = Cat("Meowth") // 自动提取匹配的属性,仅额外传入新增的price参数 val c2 = LabelledGeneric[PetPersian].from( LabelledGeneric[Cat].to(c1) :+ ('price ->> 10000) )
内容的提问来源于stack exchange,提问作者user2167582
相关产品推荐
相关产品推荐

