如何从Scala中的重写方法返回正确的类型?

时间:2013-02-04 01:46:03

标签: scala types subclassing method-overriding

作为Scala的新手,我偶然发现了SubClassing和Overriding方法看似简单的观点。

我专门设置了Set:

    class SpecializedSet [T](s:Int, b: Boolean) (implicit ordering: Ordering [T]) extends TreeSet [T] { 
      override def + (t: T): SpecializedSet [T] = {

           if (this.isEmpty) {

              s = s + 1

              // I want to add an element to the Set
              super.+ (t) 

           }
           ....
       }

在使用此课程的网站上,我这样做:

       class Driver {

         var e = new SpecializedSet [MyEarlierDefinedType](3,false);

         ......

         val elem1 = new MyEarlierDefinedType()

         e = e + eleme1 

         ......
     }

编译器立即抱怨:

  

类型不匹配; found:scala.collection.immutable.TreeSet [T] required:org.personal.exercises.SpecializedSet [T]

我知道重写的'+'方法必须返回'SpecializedSet'类型 - 一个Subtype - 而仅仅调用super。+()不能实现。

它与super。+()返回的TreeSet不同,它是在其位置创建的新TreeSet。我想我现在必须自己创建一个SpecializedSet()的新实例,使用这个新的TreeSet。我被困在这里。如何使用TreeSet 创建一个新的SpecializedSet(),它是超类型?在这种情况下,Scala世界中使用的成语是什么? 在这里使用asInstanceOf()是最合适和简短的答案吗?但是,一直不鼓励使用那种方法吗?

我是否必须在其中创建一个定义apply()方法的SpecializedSet的伴随对象?或者,我是否必须更深入地使用Scala: how to write method that returns object typed to implementation type of receiverSubclasses and return types及其他相关链接中描述的特征概念?或者,按照http://www.scala-lang.org/docu/files/collections-api/collections-impl.html中更复杂的方式创建 Builder

我也经历过这个问题(和答案):Extending a Scala collection - 它们肯定是有用的 - 但不知何故,我认为它还有比我理解的更多。例如,该链接中的一个解决方案是在函数签名中明确提到Baseclass的类型,因此:

      override def + (t: T): TreeSet [T] = { // instead of SpecializedSet 
             ......

但是,在某种程度上,这不是违反方法调用者的期望吗?我很困惑。

解决方案是否必须如此链接中所述那样参与?我失踪的明显点是什么?任何指针都会有所帮助。我搜索的程度相当大,但如果我的问题是重复的,请耐心指导我。

1 个答案:

答案 0 :(得分:1)

我更喜欢扩展相应的特性并通过合成而不是直接继承来使用类:

class SpecializedSet[T](s: Int, b: Boolean)(implicit ordering: Ordering[T]) extends SortedSet[T] {
  private var ts = new TreeSet[T]()
  override def +(t: T): SpecializedSet[T] = {
    ts += t
    this
  }
  override def -(t: T): SpecializedSet[T] = {
    ts -= t
    this
  }
  override def contains(t: T): Boolean = ts.contains(t)
  override def iterator(): Iterator[T] = ts.iterator
  override def ordering(): Ordering[T] = ts.ordering
  override def rangeImpl(from: Option[T], until: Option[T]) = ts.rangeImpl(from, until)
}

我认为这种方法更加新手友好,因为它避免了直接类继承和(直接)调用super。这个非常简单的解决方案的缺点是我们引入了可变性。这可以通过重新设计构造函数来解决,这样就可以使成员成为val并真正返回一个新的修改后的SpecializedSet实例,而不是this