考虑这个例子:
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
委托给它。但是,我想知道是否有可能没有额外的成员。
答案 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]
的内容。