Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/scala/18.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Scala 如何强制子类使用更具体的返回类型重写继承的方法_Scala_Inheritance_Overriding - Fatal编程技术网

Scala 如何强制子类使用更具体的返回类型重写继承的方法

Scala 如何强制子类使用更具体的返回类型重写继承的方法,scala,inheritance,overriding,Scala,Inheritance,Overriding,考虑这个例子: trait SpecialIntIterable extends Iterable[Int] { override def iterator: Iterator[Int] = ??? // implementation not relevant override def tail : SpecialIntIterable // plus some more methods... } class MyPrimeIterable extends SpecialI

考虑这个例子:

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

}
我试图强制
specialLiterable
的所有子类实现
tail
,因此它再次返回
specialLiterable
。这可能吗

当前我遇到以下编译器错误:

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] {
Edit:我发现的一个解决方案是在
specialLiterable
中引入一个抽象助手方法(例如称为
rest
),并让
tail
委托给它。但是,我想知道,如果没有一个额外的成员,这是否是可能的。

在本文中,这被称为“相同结果类型原则”。在集合库中,这是通过模板类实现的,模板类的名称以
Like
结尾,有时还混合了一些F-bound多态性。本质上,如果你想要一个看起来像这样的界面

trait Foo {
  def makeResult: Foo // how enforce same-result-type ?
}
但您希望强制执行,而不是所有实现子类都返回自己类型的内容,您可以修改
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
选择不扩展
SpecialLiterableLike
,它仍然必须实现一个
tail
,该tail至少返回一个
SpecialLiterable

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


这类似于扩展,例如
IndexedSeq[X]
:您可以选择不实现
IndexedSeqLike[X,MyType]
,因此“相同的结果类型”属性将稍微恶化,但
tail
的结果类型仍然至少是
IndexedSeq[X]
,而不是
Iterable[X]
或比
索引eq[X]
弱的东西

谢谢你的回答!然而,这似乎并不能真正解决我的问题
MyPrimeIterable
仍然可以决定不实现tail,或者使用更通用的返回类型实现tail。顺便说一下,我不要求返回类型相同(即,
MyPrimeIterable
),只要求是抽象的
specialiterable
。在上面的示例中,
MyPrimeIterable
不可能实现
specialiterable
tail
。它可以删除
specialLiterable[MyPrimeLiterable]
,但不能删除
tail
必须至少返回一个
specialLiterable
的要求。还是我遗漏了什么?更新了我的答案,专门解决了
tail
返回类型的界限。我想我现在明白了:如果
MyOtherIterable
根本不覆盖
tail
,它将自动获得正确的类型
specialliterable
。我很困惑,因为我可以注释
def tail…
行,但它仍然在编译。所以没有直接的方法“取消定义”一个超类的方法来强制子类重新实现它?或者至少强迫他们使用比超级实现的返回类型更具体的返回类型来实现它?@lex82 Ah,那么你想用扩展特性中的抽象实现来覆盖超级特性中的具体实现?不幸的是,这是错误的。我认为这与如何在线性化特征链中解决正确的方法实现有关:它简单地将线性化链自下而上,然后选择第一个实现的方法。似乎没有办法“抽象地重新阴影化”一个已经实现的方法……也许我误解了这个问题,因为我不理解“比什么更具体?”@Andreytukin,我的意思是比
Iterable[Int]
更具体。