5

既存のキーの値を上書きしようとするとスローされる Map が必要です。私は試した:

trait Unoverwriteable[A, B] extends scala.collection.Map[A, B] {
    case class KeyAlreadyExistsException(e: String) extends Exception(e)

    abstract override def + [B1 >: B] (kv: (A, B1)): Unoverwriteable[A, B1] = {
        if (this contains(kv _1)) throw new KeyAlreadyExistsException(
            "key already exists in WritableOnce map: %s".format((kv _1) toString)
        )
        super.+(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): Unoverwriteable[A, B] = super.-(key)
}

そして得た:

<console>:11: error: type mismatch;
 found   : scala.collection.Map[A,B1]
 required: Unoverwirteable[A,B1]
               super.+(kv)
                      ^
<console>:16: error: type mismatch;
 found   : scala.collection.Map[A,B]
 required: Unoverwirteable[A,B]
           abstract override def -(key: A): Unoverwirteable[A, B] = super.-(key)
                                                                           ^

私は Scala にまったく慣れていないので、これを克服する方法がわかりません。何か助けはありますか?:)

編集: Scala 2.8.0.Beta1-prerelease を使用しています (これにより、scala.collection にいくつかの変更が加えられます)

4

3 に答える 3

4

でメソッドをオーバーライドしているMapため、特性を戻り値の型として定義することはできません。

最も簡単な解決策は、型を省略することです。

abstract override def + [B1 >: B] (kv: (A, B1)) = { /* ... */ }
// ...
abstract override def -(key: A) = super.-(key)

または、明示的にスーパー タイプを追加することもできます。

import scala.collection.Map
abstract override def +[B1 >: B] (kv: (A, B1)): Map[A, B1] = { /* ... */ }
// ...
abstract override def -(key: A) = super.-(key): Map[A, B]

+ただし、他のメソッドは に委譲するだけなので、オーバーライドするだけでよいと思いますMap

于 2010-02-13T23:13:06.083 に答える
4

これにより、コンパイルエラーが修正されました:

trait Unoverwriteable[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] = {
        if (this contains(kv _1)) throw new KeyAlreadyExistsException(
            "key already exists in WritableOnce map: %s".format((kv _1) toString)
        )
        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)
}

ただし、次のように を本当に飾りたいと思いますcollection.mutable.Map#+=

trait Unoverwriteable[A, B] extends collection.mutable.Map[A, B] {
  case class KeyAlreadyExistsException(e: String) extends Exception(e)

  abstract override def +=(kv: (A, B)): this.type = {
    if (this contains (kv _1))
      throw new KeyAlreadyExistsException("key already exists in WritableOnce map: %s".format((kv _1) toString))
    super.+=(kv)
  }
}
于 2010-02-13T23:17:41.703 に答える
3

少し暗黙の魔法で scala.collection.immutable.Map を使用してそれを行うことができます。つまり、インターフェイスで 1 つの追加メソッドと暗黙的な変換を定義します。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)
   }
}
于 2010-02-14T22:43:50.490 に答える