作为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 receiver和Subclasses 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
......
但是,在某种程度上,这不是违反方法调用者的期望吗?我很困惑。
解决方案是否必须如此链接中所述那样参与?我失踪的明显点是什么?任何指针都会有所帮助。我搜索的程度相当大,但如果我的问题是重复的,请耐心指导我。
答案 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
。