如何强制子类使用更具体的返回类型覆盖继承的方法

时间:2018-02-16 12:40:49

标签: scala inheritance override

考虑这个例子:

trait SpecialIntIterable extends Iterable[Int] {

  override def iterator: Iterator[Int] = ??? // implementation not relevant

  override def tail : SpecialIntIterable

  // plus some more methods...

}

class MyPrimeIterable extends SpecialIntIterable {

  override def tail : SpecialIntIterable = ??? // implementation not relevant

}

我正在尝试强制SpecialIntIterable的所有子类实现tail,以便它再次返回SpecialIntIterable。这可能吗?

目前我收到以下编译错误:

overriding method tail in trait SpecialIntIterable of type => de.cointrade.trader.SpecialIntIterable;     
method tail in trait TraversableLike of type => Iterable[Int] has incompatible type;
(Note that method tail in trait SpecialIntIterable of type => de.cointrade.trader.SpecialIntIterable is abstract,
and is therefore overridden by concrete method tail in trait TraversableLike of type => Iterable[Int])
trait SpecialIntIterable extends Iterable[Int] {

编辑:我找到的一个解决方案是在rest中引入一个抽象辅助方法(例如称为SpecialIntIterable)并让tail委托给它。但是,我想知道是否有可能没有额外的成员。

1 个答案:

答案 0 :(得分:3)

Architecture of Scala Collections中,这被称为"相同结果类型原则"。在集合库中,这是通过名称以Like结尾的模板类实现的,偶尔会混合一些F绑定多态。基本上,如果你想要一个看起来像这样的界面

trait Foo {
  def makeResult: Foo // how enforce same-result-type ?
}

但是你要强制执行,而不是Foo所有实现子类都返回自己类型的东西,你修改Foo如下:

trait FooLike[+Repr] {
  def makeResult: Repr
}

然后将子类实现为

class Bar extends FooLike[Bar] {
  def makeResult: Bar = ??? // now `Bar` is enforced as return type
}

在您的情况下,您可以尝试这样的事情:

import scala.collection.IterableLike
import scala.collection.mutable.Builder

trait SpecialIntIterableLike[+Repr] extends IterableLike[Int, Repr]

abstract class SpecialIntIterable 
  extends Iterable[Int] 
  with SpecialIntIterableLike[SpecialIntIterable] {

  override def newBuilder: Builder[Int, SpecialIntIterable] = ???
}

class MyPrimeIterable extends SpecialIntIterable with SpecialIntIterableLike[MyPrimeIterable] {
  def iterator: Iterator[Int] = ???
  override def tail : MyPrimeIterable = ???                    // must override, otherwise compile-time errors
  override def newBuilder: Builder[Int, MyPrimeIterable] = ??? // must override, otherwise compile-time errors
}

请注意必须覆盖newBuilder - 方法以解决冲突(在上面的链接文档中提到了这一点)。

修改

即使您的MyPrimeIterable选择不延长SpecialIntIterableLike,它仍然必须实施至少返回tail的{​​{1}}:< / p>

SpecialIntIterable

如果我们尝试放宽class MyOtherIterable extends SpecialIntIterable { def iterator: Iterator[Int] = ??? override def newBuilder: Builder[Int, SpecialIntIterable] = ??? // def tail: Iterable[Int] = List(0) // won't compile } 的返回类型,则无法编译,因为tail扩展了SpecialIntIterable

这类似于扩展例如SpecialIntIterableLike[SpecialIntIterable]:您可以选择不实施IndexedSeq[X],因此&#34;同一结果类型&#34; -property会稍微恶化,但IndexedSeqLike[X, MyType]的结果类型仍然至少为tail ,而不是IndexedSeq[X]或弱于Iterable[X]的内容。