Deshacerse por completo de la covarianza sería, por supuesto, poco sólido y no está permitido. Dado m: Map[A, String]
, y v : Any
, puede hacer val mm : Map[A, Any] = m + v
. Esto es lo que dice la definición Map
, y todos los implementadores deben seguir. Su clase puede ser invariante, pero debe implementar la interfaz covariante completa de Map.
Ahora redefinir +
para arrojar un error es una historia diferente (no muy sonora todavía). El problema con su nuevo método +
es que después del borrado de genéricos, tiene la misma firma que el otro método +
. Hay un truco: agregue un parámetro implícito, para que tenga dos parámetros en la firma, lo que lo hace diferente del primero.
def +(kv : (A,B))(implicit useless: A <:< A) : MyMap[A,B]
(que en realidad no importa cuál sea implícita parámetro que está buscando, siempre y cuando uno se encuentra implicit useless: Ordering[String]
. Funciona igual de bien)
Haciendo eso, usted tiene el problema habitual con sobrecarga . Si agrega una B sin que el compilador lo sepa, se invocará el método que falla. Podría ser mejor realizar una verificación de tipo allí para que las instancias B sean aceptadas lo que sea. Eso requeriría obtener un Manifiesto [B] en su mapa.
¿Tal vez podría usar un mapa de miembros en lugar de derivar? – Owen
Además, ¿por qué necesita ser invariante? Pensé (aunque no sé mucho Scala) la única vez que necesitas invarianza es si puede ser tanto una fuente como un receptor, pero los mapas son inmutables por lo que no puede ser un sumidero. – Owen
Quiero implementar un mapa bidireccional. No es un gran problema si implemento Map, y simplemente delego a los dos mapas internos que definen el mapeo hacia adelante y hacia atrás, pero necesito la invarianza en ese caso. –