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 № 1Se 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 def
s, senza menzionare la mappa A
.