开发者

Scala contravariance difficulties

开发者 https://www.devze.com 2023-03-31 10:39 出处:网络
I\'m new with Scala so I\'m starting with 开发者_开发知识库rewriting my old code in Scala. Now, I\'m rewriting a Map, that contains some values and \"history\" of their modifications (like adding, del

I'm new with Scala so I'm starting with 开发者_开发知识库rewriting my old code in Scala. Now, I'm rewriting a Map, that contains some values and "history" of their modifications (like adding, deleting etc):

import scala.collection.immutable._
class Storage[A,+B](private var oldValues: Map[A,B]) extends Map[A,B] {
    private var addedValues = new HashMap[A,B]
    private var modifiedValues = new HashMap[A,B]
    private var deletedValues = new HashSet[A]  
}

When I overriding method "+" I can't compile it:

override def +[B1 >: B](kv: (A,B1)) = {
    deletedValues = deletedValues - kv._1
    addedValues = addedValues + kv //type mismatch; found : (A, B1) required: (A, B)
    modifiedValues = modifiedValues + kv //type mismatch; found : (A, B1) required: (A, B)
    currentValues()
}

Could someone tell me what can I do in this kind of situation?


The problem is the covariance of (the value type) B. Since you're using mutable state, you should probably use the mutable Map trait, which isn't covariant in type B anyway. How about extending the HashMap implementation? The following compiles, but I haven't tested it,

import collection.mutable._

class Storage[A,B](private var oldValues: Map[A,B]) extends HashMap[A,B] {
  private var addedValues: Map[A,B] = new HashMap[A,B]
  private var modifiedValues: Map[A, B] = new HashMap[A,B]
  private var deletedValues: Set[A] = new HashSet[A]  

  // Overriding this method will redefine the behavior of HashMap.put and HashMap.+= 
  override def addEntry(e: DefaultEntry[A, B]) {
    super.addEntry(e)
    // your extension code below
    val kv = (e.key, e.value)
    deletedValues -= kv._1
    addedValues += kv
    modifiedValues += kv
    // currentValues() // not defined yet
  }
}

Calls like storage += (key, value) will use your modified addEntry method. If you haven't done so already, you might want to familiarize yourself with the source-code for HashMap linked from the ScalaDoc.


You could make your class immutable.

import scala.collection.immutable._

class Storage[A,+B] private (
   val oldValues: Map[A,B] = Map(),
   val addedValues: Map[A, B] = Map(),
   val modifiedValues: Map[A, B] = Map(),
   val deletedValues: Set[A] = Set()) extends Map[A,B] {
  override def +[B1 >: B](kv: (A,B1)) =
    new Storage(oldValues,
            addedValues + kv,
            modifiedValues + kv,
            deletedValues - kv._1)
  ...
} 
0

精彩评论

暂无评论...
验证码 换一张
取 消