给定Scala中的Map [String,Int],我想创建一个特性,允许我为add和get方法添加额外的逻辑。这样做的正确语法是什么? (注意:我也想在每种情况下调用super方法)
我尝试过类似的事情:
var mymap: Map[String, Int] with mytrait[String, Int] = Map[String, Int]()
trait mytrait[A, B] {
abstract override def +[ B1 >: B] (kv: (A, B1)) : Map[A, B1] = { /* ... */ }
}
但是解释器抱怨所以我显然在语法上遗漏了一些东西,特别是使用了类型参数。
非常感谢您的帮助
更具体一点:我所拥有的是我的代码中已经存在的地图,所以不是重写我的程序的大块,我想在+方法中添加逻辑并获取Map的方法以便它每次将项目添加到程序中其他位置的地图时,都会执行额外的逻辑。因此,为什么我选择了一个特性来为地图添加功能
这是我目前的代码:
trait RegManager[A, B] extends scala.collection.Map[A, B] {
case class KeyAlreadyExistsException(e: String) extends Exception(e)
abstract override def + [B1 >: B] (kv: (A, B1)): scala.collection.Map[A, B1] = {
super.+[B1](kv)
}
abstract override def get(key: A): Option[B] = super.get(key)
abstract override def iterator: Iterator[(A, B)] = super.iterator
abstract override def -(key: A): scala.collection.Map[A, B] = super.-(key)
}
var regs = new scala.collection.Map[String, Int] with RegManager[String, Int]
更新 最后,我选择了一个包装器样式实现(Decorator DP)来完成工作。我只有6个月的时间进入我的Scala职业生涯,所以我可能还没有正确理解特征的能力呢?!很棒的语言!
答案 0 :(得分:1)
MyTrait[A,B] extends Map[A,B]
或MyTrait[A,B] {this: Map[A,B] => ...
抱歉,实际上你不太可能以这种方式开展这项工作。
我的回答的第一部分与你的MyTrait声明没有引用Map的事实有关,因此它不可能覆盖Map的+。你需要像
这样的东西trait MyTrait[A,B] extends Map[A,B] {
abstract override def +[B1 >: B](kv: (A, B1)) : Map[A, B1] = {
println("adding to map") // this is the new part
super.+(kv)
}
}
然而,由于很多原因,这不会让你走得太远:
宣言中的
var mymap: Map[String, Int] with mytrait[String, Int] = Map[String, Int]()
值Map[String, Int]()
的类型为Map,与您的特征无关。声明mymap
类型的变量Map with mytrait
将不会如此。它只会阻止它编译。
MyTrait必须出现在地图的创建中,而不仅仅是变量的类型声明中。这就像new Map[A,B] with MyTrait[A,B]
(请注意new
)。
但是,Map
是一个特征,而不是具体的类,所以你必须引入一些具体的实现。如果你设法做到这一点,那么你必须要小心,+返回的新地图也混合了MyTrait类型(当然你的具体实现不太可能)。否则,一旦添加了一个元素,就会回到没有MyTrait的Map。
答案 1 :(得分:0)
您无法向现有对象添加特征。无法动态添加特征,只能在创建对象时添加特征。 你可以:
+
mnethod,您需要使用自己的方法名称。+
作为方法名称。