Dificultades de contravarianza de Scala

Soy nuevo en Scala, así que estoy empezando a reescribir mi código antiguo en Scala. Ahora, estoy reescribiendo un mapa, que contiene algunos valores y el "historial" de sus modificaciones (como agregar, eliminar, 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]  
}

Cuando anulo el método "+" no puedo compilarlo:

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()
}

¿Alguien podría decirme qué puedo hacer en este tipo de situación?

preguntado el 27 de agosto de 11 a las 23:08

2 Respuestas

El problema es la covarianza de (el tipo de valor) B. Dado que está usando el estado mutable, probablemente debería usar el mutable Map rasgo, que no es de tipo covariante B de todas formas. ¿Qué tal extender el HashMap ¿implementación? Lo siguiente compila, pero no lo he probado,

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
  }
}

Llama como storage += (key, value) usará tu modificado addEntry método. Si aún no lo ha hecho, es posible que desee familiarizarse con el código fuente de HashMap vinculado desde el ScalaDoc.

Respondido 28 ago 11, 20:08

Podrías hacer que tu clase sea inmutable.

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)
  ...
} 

Respondido 29 ago 11, 05:08

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.