gpt4 book ai didi

scala - 有效地序列化案例类

转载 作者:行者123 更新时间:2023-12-04 08:45:46 29 4
gpt4 key购买 nike

对于我正在开发的图书馆,我需要提供一个高效、方便和 类型安全 序列化scala类的方法。理想的情况是,如果用户可以创建一个案例类,并且只要所有成员都是可序列化的,那么它也应该是无缝的。我在序列化和反序列化阶段都准确地知道类型,因此不需要(也负担不起)将任何“模式”信息作为序列化格式的一部分(如 Java 对象序列化)。

我一直在玩一些想法,这个想法似乎非常接近。我在这里看到的主要问题是用户必须如何指定类的“应用”和“取消应用”功能。由于这些是真正的静态函数,我想知道是否有可能让编译器找到它。

这是一个自包含的示例:

trait InOut[T] {
// just keeping things simple, for illustration purposes
def toWire(x: T): Array[Byte]
def fromWire(v: Array[Byte] ): T
}

object InOutConversions {
// Pretend these are implemented properly

implicit def Int = new InOut[Int] {
def toWire(x: Int): Array[Byte] = Array[Byte]()
def fromWire(v: Array[Byte] ): Int = 44
}

implicit def String = new InOut[String] {
def toWire(x: String): Array[Byte] = Array[Byte]()
def fromWire(v: Array[Byte] ): String = "blah"
}

// etc... for all the basic types
}

然后我需要一个这样的函数:
def serialize2[T, A1 : InOut, A2 : InOut](unapply : T => Option[Product2[A1, A2]])(obj : T) : Array[Byte] = {
val product : Product2[A1, A2] = unapply(obj).get
implicitly[InOut[A1]].toWire(product._1) ++ implicitly[InOut[A2]].toWire(product._2)
}

这将允许用户非常容易地使用它。例如
case class Jesus(a: Int, b: String)
val j = Jesus(4, "Testing")
serialize2 (Jesus.unapply(_)) (j)

但正如你所看到的,最后一行真的很糟糕。肯定有可能改进吗? (给定一个耶稣,我当然可以找到'unapply'静态方法)

最佳答案

因为没有获取给定案例类的伴随对象的通用方法,所以您将添加做一些额外的工作。我看到三个选项:

  • 您可以使用结构类型,但会降低性能
  • 您可以使用一个小类型类来隐式解析正确的 unapply方法。
  • 您可以添加 toTuple方法到案例类实例。

  • 例如:
    trait ToTuple2[A1,A2] {
    def toTuple: (A1,A2)
    }

    case class Jesus(a: Int, b: String) extends ToTuple2[Int,String] {
    val toTuple = (a,b)
    }

    def serialize2[T <: ToTuple2[A1,A2], A1 : InOut, A2 : InOut](obj : T): Array[Byte] = {
    val product : Product2[A1, A2] = obj.toTuple
    implicitly[InOut[A1]].toWire(product._1) ++ implicitly[InOut[A2]].toWire(product._2)
    }

    选项 2 的代码示例:
    case class Jesus(a: Int, b: String)

    trait Unapply2[T,A1,A2] {
    def asTuple( t: T ): (A1,A2)
    }

    implicit val UnapJesus = new Unapply2[Jesus,Int,String] {
    def asTuple( j: Jesus ) = Jesus.unapply(j).get
    }

    def serialize2[T, A1, A2](obj : T)
    (implicit unap: Unapply2[T,A1,A2], inout1: InOut[A1], inout2: InOut[A2]) : Array[Byte] = {
    val product : Product2[A1, A2] = unap.asTuple(obj)
    inout1.toWire(product._1) ++ inout2.toWire(product._2)
    }

    你应该看看 SBinary ,看起来很像。

    关于scala - 有效地序列化案例类,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7749316/

    29 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com