【问题标题】:Extending built-in collections, issues with built-in methods扩展内置集合,内置方法的问题
【发布时间】:2011-03-29 04:42:50
【问题描述】:

我是一个 Scala 新手,如果这是一个愚蠢的问题,请原谅我,但是这里......

想象一下,我希望创建一个包含其他方法的扩展 Map 类型。我可以看到一些方法来做到这一点。第一个是组合:

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
}

构图有点尴尬,因为你必须经常引用里面的东西。继承是相当自然的,但对我来说有一个皱纹(稍后会更多)。 Traits 似乎是一种非常优雅的方法,使用“with”结构非常好,但对我来说也有问题。

我遇到的问题是使用 ++ 之类的方法。他们返回一张新地图。所以假设上面提到的“我的方法”希望向地图添加一些东西(只是一个例子,我知道地图已经有了这个),例如

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] 特征?我考虑过创建一个新的不可变地图,该地图已预先填充,然后标记为“with Path[V]”,但没有这样的构造函数可用于创建预先填充的地图。

我怀疑(虽然我还没有确认)使用继承我会遇到类似的问题。我可以添加一个新方法来向地图添加一个新条目,但我不会得到我想要的“路径 [V]”。组合方法似乎是唯一的方法。

我希望这很清楚。评论?

【问题讨论】:

标签: scala traits


【解决方案1】:

也许最简单的方法是使用MapProxy trait:

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

这消除了组合方法的尴尬,允许您将Path 视为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 伴随对象中定义),那么您也可以将Map 视为Path

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

有一个类似的SeqProxy trait 用于向Seq 添加行为。

在更一般的情况下,解决方案是使用pimp my library pattern。这个related question 有一个例子。

【讨论】:

  • 非常感谢您不仅提供解决方案,还提供如此全面的解释。这是非常酷且有用的信息。
  • MapProxy 自 Scala 2.11.0 以来已被弃用,因此您现在应该尽可能避免使用它。
猜你喜欢
  • 2011-10-08
  • 2014-09-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-10-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多