Scala:隐式转换大小写对的通用解决方案类
Scala: Generic solution to implicitly convert pairs of case classes
我正在寻找一种使用隐式转换大小写对 类 的通用方法。为了具体说明,我正在编写一个新的配置库,它必须保持与现有配置库的向后兼容性。为了使这种转换尽可能轻松,我希望使用隐含函数将新案例 类 按需转换为旧案例。
在下面的示例中,1
类 在旧库中,2
类 来自新库。我在伴随对象上使用 apply
从 Config
实例中提取实际数据(使用 Typesafe 的 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
-> B2
, etc) 但可以使用一个通用隐式来处理所有这些。目标是能够通过简单地导入隐式来为下面的 a1
方法使用 A2
的实例:
trait Foo {
def a1: older.A1
}
我已经用头撞墙几个小时了,想不出解决办法。
提前致谢。
它是否解决了您的问题,还是我误解了什么?
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
自然地,在我离开这个问题几个小时后,我想出了解决方案。尴尬的是,它也非常简单。
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 将案例 类 转换为 JSON 并返回以执行实际实例化的能力。似乎比搞乱反射更容易。
感谢帮助!
我正在寻找一种使用隐式转换大小写对 类 的通用方法。为了具体说明,我正在编写一个新的配置库,它必须保持与现有配置库的向后兼容性。为了使这种转换尽可能轻松,我希望使用隐含函数将新案例 类 按需转换为旧案例。
在下面的示例中,1
类 在旧库中,2
类 来自新库。我在伴随对象上使用 apply
从 Config
实例中提取实际数据(使用 Typesafe 的 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
-> B2
, etc) 但可以使用一个通用隐式来处理所有这些。目标是能够通过简单地导入隐式来为下面的 a1
方法使用 A2
的实例:
trait Foo {
def a1: older.A1
}
我已经用头撞墙几个小时了,想不出解决办法。
提前致谢。
它是否解决了您的问题,还是我误解了什么?
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
自然地,在我离开这个问题几个小时后,我想出了解决方案。尴尬的是,它也非常简单。
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 将案例 类 转换为 JSON 并返回以执行实际实例化的能力。似乎比搞乱反射更容易。
感谢帮助!