在 Scala 中序列化时更改不可变变量值

changing immutable variable values while serialization in scala

我有一个case class User。我必须使用 kryo 对其进行序列化。这是我的 class。

在实施 Kryo 的 read() 时遇到问题。我的变量有 val 类型。正如我们所知,我们无法更改 val 的值。

case class User(name : String, age : int) extends KryoSerializable {

  def this()={
    this("",0)
  }

// 
 override  def read(kryo : Kryo, input :  Input) {
 // here i'm getting error. i can't override name because its val
 name = input.readString()
  age = input.readInt()

    println("-----------Read method of Kryo")

  }

  override def write(kryo : Kryo, output :  Output) {
   output.writeString(name)
   output.writeInt(age)
     println("--------Write method of Kryo")
  }
}

请指导我,我该怎么做?

如果您没有任何紧迫的理由为用户使用 case class,我建议您不要使用 case class。因为您必须将姓名和年龄声明为变量。 case class 不应该 是可变的。

这里有一些东西,可能会完成你想要的,而不需要 User case class:

class User (private var _name : String, private var _age : Int) extends KryoSerializable {

  def name = _name
  def age = _age

  override def read(kryo : Kryo, input :  Input) {
    // here i'm getting error. i can't override name because its val
    _name = input.readString()
    _age = input.readInt()

    println("-----------Read method of Kryo")

  }

   override def write(kryo : Kryo, output :  Output) {
    output.writeString(_name)
    output.writeInt(_age)
    println("--------Write method of Kryo")
  }
}

object User {
  def apply(name: String, age: Int = 0): User = new User(name, age)
}

由于 User 是一个案例 class,您可以使用 copy 创建一个新的 User,同时更新(部分)值。

case class User(name: String = "", age: Int = 0)

val empty = User() // User = User(,0)
val alice = empty.copy("Alice", 40) // User = User(Alice,40)

但是由于 KryoSerializable 你需要修改对象本身(read 的类型是 Unit),你不能 return 一个新的 User 实例,因此如果您想继续使用案例 class.

,最好使用外部 Serializer[User]
class UserSerializer extends Serializer[User] {
  def write (kryo: Kryo, output: Output, user: User): Unit = {
    output.writeString(user.name)
    output.writeInt(user.age)
  }

  def read(kryo: Kryo, input: Input, `type`: Class[User]): User = 
    User(
      name = input.readString()
      age = input.readInt()
    )
}