Scala:隐式转换大小写对的通用解决方案类

Scala: Generic solution to implicitly convert pairs of case classes

我正在寻找一种使用隐式转换大小写对 类 的通用方法。为了具体说明,我正在编写一个新的配置库,它必须保持与现有配置库的向后兼容性。为了使这种转换尽可能轻松,我希望使用隐含函数将新案例 类 按需转换为旧案例。

在下面的示例中,1 类 在旧库中,2 类 来自新库。我在伴随对象上使用 applyConfig 实例中提取实际数据(使用 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 并返回以执行实际实例化的能力。似乎比搞乱反射更容易。

感谢帮助!