【问题标题】:Scala: How can I make my immutable classes easier to subclass?Scala:我怎样才能让我的不可变类更容易子类化?
【发布时间】:2011-11-05 20:36:17
【问题描述】:

我最近创建了一个不可变类,它支持 +、- 等操作,当它发生变化时会返回该类的新实例。

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

根据我目前对 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. 使用可变数据结构。这可能是最简单、最快的解决方案,但我会失去使用不可变数据结构的好处(我仍然希望了解更多)。

我相信这已经讨论过很多次了,对于再次提问,我深表歉意。我用谷歌搜索了一个重复的问题,但没有成功,所以我的搜索词一定是结构不好。

提前致谢,

多布斯

【问题讨论】:

  • 通过阅读有关Lenses 的内容,我认为它们可能会有所帮助,但我自己并没有尝试或采用它们,所以也许我错了。

标签: scala inheritance base-class


【解决方案1】:

您可以使用实现特征,就像集合类所做的那样,由具体类型参数化。例如,类似:

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

【讨论】:

    猜你喜欢
    • 2017-04-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-09-07
    • 2011-06-14
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多