1

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

我因此专门设置了一个集合:

    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 

         ......
     }

编译器立即抱怨:

类型不匹配; 找到:scala.collection.immutable.TreeSet[T] 需要:org.personal.exercises.SpecializedSet[T]

我知道重写的 '+' 方法必须返回一个 'SpecializedSet' 类型 - 一个子类型 - 并且仅仅调用 super.+() 并不能实现这一点。

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

我是否必须创建一个 SpecializedSet 的伴随对象,在其中定义一个 apply() 方法?或者,我是否必须更深入地使用Scala 中描述的 Traits 概念:如何编写将对象类型化为接收器子类的实现类型以及返回类型和其他相关链接的方法?或者,按照http://www.scala-lang.org/docu/files/collections-api/collections-impl.html中创建Builder的更复杂的方向?

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

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

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

解决方案是否必须像这些链接中所述那样参与?我遗漏的明显点是什么?任何指针都会有所帮助。我已经进行了相当大的搜索,但如果我的问题是重复的,请耐心等待并指导我。

4

1 回答 1

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 的调用。这个非常简单的解决方案的缺点是我们引入了可变性。这可以通过重新设计构造函数来解决,以便可以使成员 aval并真正返回一个新的修改SpecializedSet实例而不是this.

于 2013-02-04T10:17:14.093 回答