2013-02-04 93 views
1

作爲Scala的新手,我偶然發現了SubClassing和Overriding方法的這個看似簡單的點。如何從Scala中的overriden方法返回正確的類型?

我有專門的一組這樣的:

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。我想我現在必須使用這個新的TreeSet創建一個新的SpecializedSet()我的實例,。我被困在這裏。我如何創建一個新的SpecializedSet(),使用TreeSet 這是它的Supertype?在這種情況下,Scala世界中的成語是什麼? 是否使用asInstanceOf()這裏最合適和最簡短的答案?但是,不是一直勸阻這種方法嗎?

是否必須創建一個定義apply()方法的SpecializedSet的伴隨對象?或者,我是否必須更深入地使用Scala: how to write method that returns object typed to implementation type of receiverSubclasses and return types中描述的特徵和其他相關鏈接中描述的特徵的概念?或者,按照更復雜的方向創建Builder s like http://www.scala-lang.org/docu/files/collections-api/collections-impl.html

我也經歷了這個問題(和答案):Extending a Scala collection - 它們肯定是有用的 - 但不知何故,我認爲它比我瞭解的更多。例如,在鏈接的解決方案之一是明確提及基類的類型的函數簽名,即:

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

不過,那麼是不是違反了方法的調用者的期待, 在某種方式?我很困惑。

解決方案是否必須像這些鏈接中概述的那樣涉及?我缺少什麼明顯的觀點?任何指針都會有幫助。我已經在很大程度上進行了搜索,但如果我的問題是重複的,請耐心等待並指導我。

+2

您應該使用...使用SortedSetLike擴展TreeSet [T] [T,SpecializedSet [T]] – Eastsun

+3

您可能不應該嘗試擴展集合,直到您對Scala更加舒適。如果您確實需要,請參閱http://www.scala-lang.org/docu/files/collections-api/collections-impl.html中的示例。否則,標準收集方法將不適用於您的新收藏或將有令人驚訝的行爲。 –

回答

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) 
} 

我覺得這種做法是更新手友好,因爲它避免了直接的類繼承和(直接)調用超。這個非常簡單的解決方案的缺點是我們引入了可變性。這可以通過重新設計構造函數來解決,以便有可能使成員成爲val,並且確實返回新的已修改的SpecializedSet實例而不是this

+0

這符合我的想法,並提供了一個簡單的解決方案。事實上,對於像我這樣的新手來說,這應該是方法。謝謝@ bluenote10。 – Nirmalya

相關問題