2010-08-12 25 views
2

我是一個新手斯卡拉所以原諒我,如果這是一個愚蠢的問題,但在這裏不用...擴展內置集合,問題與內置的方法

想象我想創建一個擴展地圖類型包括其他方法。我可以看到幾種方法來做到這一點。第一個將與構圖:

class Path[V](val m: Map[V, Int]) { 
    // Define my methods 
} 

另一個將通過繼承,例如,

class Path[V] extends Map[V, Int] { 
// Define my methods 
} 

最後,我還考慮了「特質」路線,例如,

trait Path[V] extends Map[V, Int] { 
// Define my methods 
} 

組成有點尷尬,因爲你經常不得不參考裏面的東西。繼承是一個相當自然的事情,但對我來說卻是一個皺紋(更多在一秒之內)。性狀似乎是一個非常優雅的方式來做到這一點,並使用「與」構造它是非常好的,但它也有我的問題。

我遇到的皺紋是像++這樣的方法。他們返回一張新地圖。因此,讓我們假設上面提到的「我的方法」希望在地圖上添加一些東西(只是一個例子,我知道地圖已經有這個),例如,

trait Path[V] extends Map[V,Int] { 
    def addOne(v: V, i: Int): Path[V] = this + (v -> i) 
} 

由於返回類型不是Path [V],所以會產生錯誤。現在我知道我可以在新實例上使用「with」來添加Path [V]特性。但我不控制這裏新地圖的構建。有什麼方法可以添加Path [V]特性嗎?我想過創建一個新的不可變的地圖,該地圖是預先填充的,然後用「Path [V]」標記,但是沒有這樣的構造函數可以用來創建預填充的地圖。

我懷疑(雖然我還沒有證實它),我會有一個類似的問題,使用繼承。我可以添加一個新的方法來添加一個新的條目到地圖中,但我不會找回我想要的「Path [V]」。構圖方法似乎是唯一的途徑。

我希望這很清楚。註釋?

+0

請參閱http:// stackoverflow。com/questions/3374923/how-can-you-inherit-a-generic-factory-method – 2010-08-12 22:20:35

回答

6

或許要做到這一點最簡單的方法是使用MapProxy特點:通過允許您治療Path

import collection._ 

class Path[V](val self: Map[V, Int]) extends MapProxy[V, Int] { 
    // without the companion object below 
    def addOne(v: V, i: Int): Path[V] = new Path(this + (v -> i)) 
    // with the companion object below 
    def addOne(v: V, i: Int): Path[V] = this + (v -> i) 
    // other methods 
} 

// this companion object is not strictly necessary, but is useful: 
object Path { 
    implicit def map2path[V](map: Map[V, Int]): Path[V] = new Path(map) 
} 

這消除了組成辦法的尷尬,就好像它是一個Map

scala> new Path(Map("a" -> 1)) + ("b" -> 2) 
res1: scala.collection.Map[java.lang.String,Int] = Map((a,1), (b,2)) 

scala> new Path(Map("a" -> 1)).get("a") 
res2: Option[Int] = Some(1) 

如果包含從MapPath(在Path伴隨對象中定義)的隱式轉換,那麼您也可以將t REAT一個Map,就好像它是一個Path

scala> Map("a" -> 1).addOne("b", 2) 
res3: Path[java.lang.String] = Map((a,1), (b,2)) 

有一個類似SeqProxy特徵添加行爲的Seq

在更一般的情況下,解決方案是使用pimp my library pattern。這個related question就是一個例子。

+0

非常感謝你提供的不僅僅是解決方案,而是對於這樣一個全面的解釋。這是非常酷和有用的信息。 – 2010-08-13 14:15:16

+0

自從Scala 2.11.0以來,MapProxy已被棄用,所以如果可以的話,你現在應該避免使用它。 – Caoilte 2014-08-03 20:30:20