Имам изискване да използвам подклас в aHashMap, който е обявен за SuperClass. Например: Създадох суперклас и подклас. Сега създавам абстрактен клас А и конкретен клас В, който разширява А. А има променлива myMap, която е декларирана като java.util.Map[_ <: Superclass, String]
, В клас B трябва да използвам myMap, но трябва да вмъкна инстанция на SubClass вместо Superclass в myMap.following е кодът за обяснение
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
}
}
Ако се опитам да вмъкна потребителския подклас в myMap, получавам следната грешка: несъответствие на типа; found: Необходим е Subclass.type (с подклас): _ $ 2 където _ _ $ 2 <: SuperClass
Отговори:
2 за отговор № 1Ако можете да използвате SubClass
тук бихте нарушили принципа на заместването на Лисков: клас B
трябва да бъде в състояние да направи всичко, което може да се направи с A
, но в примера ти не можеш да правиш неща SuperClass
ключовете в него Map
.
Има няколко начина около него, напр. можете да параметризирате A
и 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)
}
}
Подобно решение би могло да използва членове с абстрактен тип:
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)
}
}
Не съм сигурен защо се изисква допълнителен сетер.
Като цяло мисля, че поставям var
в абстрактен клас не е добра идея. Трябва ли детайл за изпълнението да изтече така? Вероятно не. И дори ако е необходимо, наистина ли трябва да бъдеш в състояние замени пълната карта? Ако не, можете да използвате a val
, Или можете да изградите фасада за добавяне, премахване, търсене на елементи, които използвате def
и, без изобщо да споменем картата в A
.