/ / Scala: Come inserire Sottoclass anziché Superclasse in Mappa dichiarata per SuperClass - scala, classe

Scala: Come inserire Sottoclass anziché Superclasse in Mappa dichiarata per SuperClass - scala, classe

Ho l'obbligo di usare una sottoclasse in aHashMap che è stato dichiarato per SuperClass. Ad esempio: ho creato una superclasse e una sottoclasse. Ora creo una classe astratta A e una classe concreta B che estende A. A ha una variabile myMap che come dichiarata java.util.Map[_ <: Superclass, String] . In classe B, ho bisogno di usare myMap, ma ho bisogno di inserire l'istanza di SubClass invece di Superclass in myMap.following è il codice per spiegare

abstract class Superclass {
def foo(value:String): Boolean
}



class Subclass extends Superclass {
def foo(value:String) = {
true // or random boolean expression
}
}

abstract class A {
var myMap: java.util.Map[_ <: Superclass, String]
def addToMap(value:String)
}

class B extends A {
myMap = new java.util.HashMap[Subclass, String]()

def addToMap(value:String) {
val subclass = new SubClass()
myMap.put(subclass, value) // getting compilation error here
}
}

Se provo a inserire istanza di sottoclasse in myMap, ottengo l'errore seguente: tipo mancata corrispondenza; found: Subclass.type (con sottotipo di tipo sottostante) richiesto: _ $ 2 dove tipo _ $ 2 <: SuperClass

risposte:

2 per risposta № 1

Se tu potessi usare SubClass qui violerebbe il Principio di sostituzione di Liskov: Class B dovrebbe essere in grado di fare tutto ciò che può essere fatto con A, ma nel tuo esempio, non puoi roba SuperClass chiavi nella sua Map.

Ci sono molti modi per aggirarlo, ad es. potresti parametrizzare A e B:

abstract class A[S <: Superclass] {
var myMap: java.util.Map[S, String]

def addToMap(value: String)
}

class B extends A[Subclass] {

var myMap:java.util.Map[Subclass, String] = new java.util.HashMap[Subclass, String]()

def myMap(map: java.util.Map[Subclass, String]) { myMap = map }

def addToMap(value: String) {
val subclass = new Subclass()
myMap.put(subclass, value)
}
}

Una soluzione simile potrebbe invece utilizzare membri di tipo astratto:

abstract class A {

type S <: Superclass

var myMap: java.util.Map[S, String]

def addToMap(value: String)
}

class B extends A {

type S = Subclass

var myMap: java.util.Map[Subclass, String] = new java.util.HashMap[Subclass, String]()

def myMap(map: java.util.Map[Subclass, String]) {
myMap = map
}

def addToMap(value: String) {
val subclass = new Subclass()
myMap.put(subclass, value)
}
}

Non sono sicuro, perché è richiesto il setter aggiuntivo.

In generale, penso che mettere un var in una classe astratta non è una buona idea. Un dettaglio di implementazione dovrebbe fuoriuscire in questo modo? Probabilmente no. E anche se è necessario, devi essere davvero capace sostituire la mappa completa? In caso contrario, puoi usare a val. Oppure potresti costruire una facciata per aggiungere, rimuovere, interrogare gli elementi usando defs, senza menzionare la mappa A.