Scala:隐式转换案例类对的通用解决方案

时间:2016-05-19 16:24:14

标签: scala implicit-conversion

我正在寻找一种使用implicits转换案例类对的通用方法。为了具体化,我正在编写一个新的配置库,该库必须保持与现有配置库的向后兼容性。为了尽可能轻松地实现这种过渡,我希望使用implicits将新案例类别按需转换为旧版本。

在下面的示例中,1类位于旧库中,2类来自新库。我在配套对象上使用applyConfig实例中提取实际数据(使用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 - &gt; A2B1 - &gt; {{1但是,可以使用单个泛型隐式来处理所有这些。目标是只需导入隐式的<{1}}方法就可以使用B2的实例:

A2

我现在已经把头撞到墙上几个小时了,无法提出解决方案。

提前致谢。

2 个答案:

答案 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并返回执行实际实例化的能力。似乎比弄乱反思更容易。

感谢您的帮助!