我正在尝试实现一种类似于 Map 的新类型 Chunk。基本上,“Chunk”要么是 String -> Chunk 的映射,要么是字符串本身。
例如,它应该能够像这样工作:
val m = new Chunk("some sort of value") // value chunk
assert(m.getValue == "some sort of value")
val n = new Chunk("key" -> new Chunk("value"), // nested chunks
"key2" -> new Chunk("value2"))
assert(n("key").getValue == "value")
assert(n("key2").getValue == "value2")
我大部分时间都在工作,除了我对 + 运算符如何用于不可变映射感到有些困惑。
这是我现在拥有的:
class Chunk(_map: Map[String, Chunk], _value: Option[String]) extends Map[String, Chunk] {
def this(items: (String, Chunk)*) = this(items.toMap, None)
def this(k: String) = this(new HashMap[String, Chunk], Option(k))
def this(m: Map[String, Chunk]) = this(m, None)
def +[B1 >: Chunk](kv: (String, B1)) = throw new Exception(":( do not know how to make this work")
def -(k: String) = new Chunk(_map - k, _value)
def get(k: String) = _map.get(k)
def iterator = _map.iterator
def getValue = _value.get
def hasValue = _value.isDefined
override def toString() = {
if (hasValue) getValue
else "Chunk(" + (for ((k, v) <- this) yield k + " -> " + v.toString).mkString(", ") + ")"
}
def serialize: String = {
if (hasValue) getValue
else "{" + (for ((k, v) <- this) yield k + "=" + v.serialize).mkString("|") + "}"
}
}
object main extends App {
val m = new Chunk("message_info" -> new Chunk("message_type" -> new Chunk("boom")))
val n = m + ("c" -> new Chunk("boom2"))
}
此外,我们将不胜感激就总体上这种实现是否合适发表评论。
谢谢!
编辑:代数数据类型解决方案非常好,但仍然存在一个问题。
def +[B1 >: Chunk](kv: (String, B1)) = Chunk(m + kv) // compiler hates this
def -(k: String) = Chunk(m - k) // compiler is pretty satisfied with this
这里的 - 运算符似乎有效,但 + 运算符真的希望我返回 B1 类型的东西(我认为)?它失败并出现以下问题:
overloaded method value apply with alternatives: (map: Map[String,Chunk])MapChunk <and> (elems: (String, Chunk)*)MapChunk cannot be applied to (scala.collection.immutable.Map[String,B1])
Edit2:Xiefei 回答了这个问题——扩展 map 需要我用 Chunk 的超类型(B1)处理 +,所以为了做到这一点,我必须有一些实现,所以这就足够了:
def +[B1 >: Chunk](kv: (String, B1)) = m + kv
但是,我从来没有真正打算使用那个,相反,我还将包括我的实现,它返回一个块,如下所示:
def +(kv: (String, Chunk)):Chunk = Chunk(m + kv)