我有以下(简化)类包装Map
:
class Store(val values: Map[String, String]) {
def set(name: String, value: String): Store = new Store(values + (name -> value))
def remove(name: String): Store = new Store(values - name)
}
我想让其他类扩展它来覆盖,比如toString
方法:
class PrintableStore(values: Map[String, String]) extends Store(values) {
override def toString: String = values.toString
}
事后明显的问题是set
和remove
返回Store
的实例:这些方法返回的值不是正确的类型,而且我正在失去我的增强型toString
方法。
我能找到的唯一解决方案是将Store
定义为具有自我类型的特征,如下所示:
trait Store[+Self] {
this: Self =>
def values: Map[String, String]
def copy(values: Map[String, String]): Self
def set(name: String, value: String): Self = copy(values + (name -> value))
def remove(name: String): Self = copy(values - name)
}
class PrintableStore(val values: Map[String, String]) extends Store[PrintableStore] {
override def toString: String = values.toString
override def copy(values: Map[String, String]): PrintableStore = new PrintableStore(values)
}
这很好用,但需要我认为是Scala代码的惊人数量的样板:
copy
实现。Store
。这个问题有更好的解决方案,还是我被宠坏了,我的样板门限太低了? 我必须承认,虽然我觉得我理解自我类型,但我还不太习惯使用它们而且以前的代码可能完全不正确。
答案 0 :(得分:2)
您可以执行类似于集合库的操作:
trait StoreLike[T <: StoreLike[T]] {
val values: Map[String, String]
def set(name: String, value: String): T = build(values + (name -> value))
def remove(name: String): T = build(values - name)
def build(values: Map[String, String]): T
}
class Store(val values: Map[String, String]) extends StoreLike[Store] {
def build(values: Map[String, String]): Store = new Store(values)
}
class PrintableStore(val values: Map[String, String]) extends StoreLike[PrintableStore] {
override def toString: String = values.toString()
def build(values: Map[String, String]): PrintableStore = new PrintableStore(values)
}