我有一个时间的混蛋,在scala中实现了一个类型(为了我们的目的)[String,Set [Foo]],它为值中的Foos提供了额外的操作。实际实现比下面介绍的更复杂,但这是要点。我需要一个实现所有类似Map函数的类,并在作为map值的集合上提供额外的聚合。我见过的使用MapLike模式的扩展Map,尤其是this,无效。
到目前为止我得到了什么:
import scala.collection.{immutable, Map, MapLike}
class Foo(a:Int)
class CustomMap
(val underlying:Map[String,Set[Foo]] = Map[String,Set[Foo]]())
extends Map[String, Set[Foo]] with MapLike[String, Set[Foo], CustomMap] {
override def empty = new CustomMap(underlying.empty)
def -(key: String) = new CustomMap(underlying - key)
def +[B1 >: Set[Foo]](kv: (String, B1)): scala.collection.Map[String,B1] = new CustomMap(underlying + (kv._1 -> kv._2))
def get(key: String): Option[Set[Foo]] = underlying.get(key)
def iterator: Iterator[(String, Set[Foo])] = underlying.iterator
override def size = underlying.size
def getAllFoos() = underlying.values.flatten.toSet
}
val cm1:CustomMap = new CustomMap(Map("a" -> Set(new Foo(1))))
val cm2:CustomMap = cm1 + ("a" -> Set(new Foo(2)))
println(cm2.getAllFoos)
+方法和访问额外聚合方法都存在问题。
任何指针?
file.scala:12: error: type mismatch;
found : B1
required: Set[this.Foo]
def +[B1 >: Set[Foo]](kv: (String, B1)): scala.collection.Map[String,B1] = new CustomMap(underlying + (kv._1 -> kv._2))
^
file.scala:24: error: type mismatch;
found : scala.collection.Map[String,Set[this.Foo]]
required: this.CustomMap
val cm2:CustomMap = cm1 + ("a" -> Set(new Foo(2)))
^
two errors found
答案 0 :(得分:3)
+
无法返回CustomMap
,因为有时B1
不会成为Set[Foo]
,而是Set[Foo]
的其他超类型。这是您的错误的来源。 Map
和MapLike
适用于提供地图实现的类,可以安全地为其添加任何值,并返回可用的Map
。因此,Map[String, Set[Foo]]
可以随身携带("", 5)
并成为Map[String, Any]
。
您可以使用" pimp-my-library"来消除underlying
周围的包装,并避免这些问题。图案:
implicit class FooSetMap(val map: Map[String,Set[Foo]]) extends AnyVal {
def getAllFoos = map.values.flatten.toSet
}
如果您愿意使用可变地图,请查看collection.mutable.MultiMap
。这是一个mixin特性,它为mutable.Map[A, mutable.Set[B]]
的子类型增加了额外的方法来处理多重映射 - 你可以根据需要做类似的事情。