Scala:如何使我的不可变类更容易子类化?

时间:2011-08-29 08:10:14

标签: scala inheritance base-class

我最近创建了一个支持+, - 等操作的不可变类,它在更改时返回该类的新实例。

我想创建该类的子类以添加一些状态和功能但现在我遇到了一个问题,因为所有原始类的方法都返回自身的实例而不是子类。

基于我目前对Scala的有限知识,我可以想出这个:

class Foo(val bar:Int) { 
  def copy(newBar:Int) = new Foo(newBar)
  def + (other:Foo):This = copy(this.bar + other.bar) 
}
class Subclass(barbar:Int) extends Foo(barbar) { 
  override def copy(newBar:Int) = new Subclass(newBar)
  override def + (other:Subclass) = super.+(other).asInstanceOf[Subclass]
}

这里的问题非常明显 - 返回新实例的超类的所有操作都必须在子类中使用强制转换重新定义。

起初“this.type”似乎很有希望,但“this.type”只包含“this”而不包含任何其他相同类型的对象。

是否存在使不可变类易于子类化的标准模式?类似的东西:

class Foo(val bar:Int) { 
  def copy(newBar:Int):SameType = new Foo(newBar)
  def + (other:Foo) = copy(this.bar + other.bar) 
}
class Subclass(barbar:Int) extends Foo(barbar) { 
  override def copy(newBar:Int):SameType = new Subclass(newBar)
  override def + (other:Subclass) = super.+(other).asInstanceOf[Subclass]
}

这种特殊方法要求编译器要求所有子类实现一个copy()方法,该方法返回与该子类相同的类型,这对我来说完全没问题。但是,我不认为此时Scala中存在任何此类事情。

我想到的一些解决方法是:

  1. 使用委托 - 但当然我仍然会将所有方法重新实现为委托调用
  2. 使用隐式类型添加操作而不是子类化
  3. 使用可变数据结构。这可能是最简单,最快捷的解决方案,但我失去了使用不可变数据结构的好处(我仍然希望了解更多信息)。
  4. 我确信已经多次讨论这件事了,我再次向你道歉。我没有成功地向谷歌提出了重复的问题,因此我的搜索条件必须构建得很差。

    提前致谢,

    Dobes

1 个答案:

答案 0 :(得分:9)

您可以使用实现特征,就像集合类一样,它由具体类型进行参数化。例如:

trait FooLike[+A] {
  protected def bar: Int

  protected def copy(newBar: Int): A
  def +(other: Foo): A = copy(bar + other.bar)
}

class Foo(val bar: Int) extends FooLike[Foo] {
  protected def copy(newBar: Int): Foo = new Foo(newBar)
}

class Subclass(barbar: Int) extends Foo(barbar) with FooLike[Subclass] {
  protected def copy(newBar: Int): Subclass = new Subclass(newBar)
}