我正在寻找一种使用implicits转换案例类对的通用方法。为了具体化,我正在编写一个新的配置库,该库必须保持与现有配置库的向后兼容性。为了尽可能轻松地实现这种过渡,我希望使用implicits将新案例类别按需转换为旧版本。
在下面的示例中,1
类位于旧库中,2
类来自新库。我在配套对象上使用apply
从Config
实例中提取实际数据(使用Typesafe' s config库)。
package older {
case class A1(a: String)
case class B1(b: Int)
}
package newer {
case class A2(a: String)
case class B2(b: Int)
object A2 {
def apply(cfg: Config): A2 = A2(a = cfg.getString("a"))
def toOlder(a2: A2) = older.A1(a = a2.a)
}
object B2 {
def apply(cfg: Config): B2 = B2(b = cfg.getInt("b"))
def toOlder(b2: B2) = older.B1(b = b2.b)
}
}
理想情况下,我不必编写一个隐式函数来转换每个案例类(A1
- > A2
,B1
- &gt; {{1但是,可以使用单个泛型隐式来处理所有这些。目标是只需导入隐式的<{1}}方法就可以使用B2
的实例:
A2
我现在已经把头撞到墙上几个小时了,无法提出解决方案。
提前致谢。
答案 0 :(得分:1)
它能解决你的问题,还是我误解了什么?
implicit final def aToOlder(self: A2): A1 = A1(a = self.a)
implicit final def bToOlder(self: B2): B1 = B1(b = self.b)
用法:
val old: A1 = A1("John")
val oldFromNew: A1 = A2("Doe") // This will be implicitly converted from the `A2` instance to the `A1` instance
答案 1 :(得分:0)
当然,在我离开问题几个小时之后,我想出了解决方案。令人尴尬的是,它也很简单。
package older {
case class A1(a: String)
case class B1(b: Int)
}
package newer {
sealed trait Convertable[A <: AnyRef, B <: AnyRef] {
implicit val formats = DefaultFormats
implicit def convert(new: A)(implicit mB: Manifest[B]): B = {
read[B](write(new))
}
}
case class A2(a: String)
case class B2(b: Int)
object A2 extends Convertable[A2, older.A1] {
def apply(cfg: Config): A2 = A2(a = cfg.getString("a"))
}
object B2 extends Convertabe[B2, older.B1] {
def apply(cfg: Config): B2 = B2(b = cfg.getInt("b"))
}
}
另请注意,我使用Lift-JSON将case类转换为JSON并返回执行实际实例化的能力。似乎比弄乱反思更容易。
感谢您的帮助!