2010-08-12 63 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