在scala中进行序列化时更改不可变变量值

时间:2015-08-29 10:34:34

标签: scala kryo

我有case class User。我必须使用kryo序列化它。这是我的课。

实现Kryo I的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")
  }
}
请指导我,我该怎么做?

2 个答案:

答案 0 :(得分:1)

如果您没有任何紧迫的理由对用户使用case class,我建议您不要使用case class。因为您必须将name和age声明为变量。而case class

在不User case class {<1}}的情况下,您可以完成以下任务:

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)
}

答案 1 :(得分:1)

由于User是一个案例类,因此您可以使用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),因此您无法返回新的User实例,因此您将如果你想继续使用案例类,最好使用外部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()
    )
}