Scala案例类不可更改的成员

时间:2014-02-04 08:35:38

标签: class scala case

在Scala中,我有一个表示一些数据的案例类:

case class Foo( val start : Int, val end : Int )

我经常使用复制方法。

但是,我现在已经达到了我想添加额外成员作为标识符的程度,因为我想要以下等式行为:

case class NewFoo( val id : Int, val start : Int, val end : Int )
{
    override def equals( any : Any ) = any match
    {
        case other : NewFoo => id == other.id
        case _ => false
    }
}

但是,我现在想要阻止用户在复制id实例时更改NewFoo,因此,一旦创建NewFoo,其数据就会发生变化,但是它的id将始终保持不变。

这种情况可以用于案例类吗?我怀疑不是,因为它不是真正的设计目标。另一方面,我读过的关于case类的定义是它们是“普通且不可变的数据保持对象,应该完全取决于它们的构造函数参数”,这个定义似乎没有被我的用例打破

如果案例类不合适,有没有办法可以复制一个案例的功能,特别是复制方法,而没有明确的案例类?我没有使用模式匹配。

1 个答案:

答案 0 :(得分:4)

是的,你可以像这样手动实现copy方法:

sealed class NewFoo(val id: Int, val start: Int, val end: Int) {
  def copy(start: Int = start, end: Int = end) = new NewFoo(id, start, end)

  override def equals(any: Any) = any match {
    case other : NewFoo => id == other.id
    case _ => false
  }

  // don't forget to override `hashCode` with `equals`
  override def hashCode() = id.hashCode()
}

请注意,您还应该使用hashCode覆盖equals

您还可以让您的课程sealed避免此equals实施的问题。

另见Programming in Scala/Object Equality

您还可以使用此随播对象实现保存模式匹配和实例创建,而不使用newNewFoo(0, 0, 0)):

object NewFoo {
  def apply(id: Int, start: Int, end: Int) = new NewFoo(id, start, end)
  def unapply(f: NewFoo): Option[(Int, Int, Int)] = Some((f.id, f.start, f.end))
}