Вы можете сделать это, используя scala.collection.immutable.Map с небольшой неявной магией. То есть вы определяете один дополнительный метод в интерфейсе и неявное преобразование. Вот как я это сделаю в 2.7, я уверен, что в 2.8 есть разные методы для переопределения, но вы должны понять общую идею.
trait Unoverwriteable[A, B] extends scala.collection.immutable.Map[A, B] {
import Unoverwriteable.unoverwriteableMap
case class KeyAlreadyExistsException(e: String) extends Exception(e)
def underlying: scala.collection.immutable.Map[A, B]
def update [B1 >: B] (key: A, value: B1): Unoverwriteable[A, B1] = {
if (this contains(key)) throw new KeyAlreadyExistsException(
"key already exists in WritableOnce map: %s".format(key.toString)
)
underlying update (key, value)
}
def get(key: A): Option[B] = underlying get key
def elements: Iterator[(A, B)] = underlying.elements
def -(key: A): Unoverwriteable[A,B] = underlying - key
def empty[C]: Unoverwriteable[A,C] = underlying.empty[C]
def size: Int = underlying.size
}
Затем вы определяете неявное в сопутствующем объекте:
object Unoverwriteable {
implicit def unoverwriteableMap[A, B](map0: scala.collection.immutable.Map[A, B]): Unoverwriteable[A, B] =
new Unoverwriteable[A, B] { def underlying = map0 }
}
Чтобы использовать его, добавьте аннотацию типа Unwriteable на вашу карту. Если вы раскомментируете последние 2 строки в основном методе, вы получите KeyAlreadyExistsException по желанию.
object UOMain {
def main(args: Array[String]): Unit = {
val map0 = Map((1 -> 1), (2 -> 2)): Unoverwriteable[Int, Int]
println("map0="+ map0)
val map1 = map0 - 2
println("map1="+ map1)
//val map2 = map1 + (1 -> 1000)
//println("map2" + map2)
}
}