我需要在HashMap中使用已为SuperClass声明的子类。
例如:我创建了一个超类和一个子类。
现在我创建一个抽象类A和一个扩展A的具体类B.
A有一个变量myMap,声明为java.util.Map[_ <: Superclass, String]
。在B类中,我需要使用myMap,但我需要在myMap中插入SubClass的实例而不是Superclass。下面是解释的代码
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中插入Subclass实例,我会收到以下错误: 类型不匹配; found:需要Subclass.type(带底层类型Subclass):_ $ 2其中type _ $ 2&lt ;:SuperClass
答案 0 :(得分:2)
如果您可以在此处使用SubClass
,则会违反Liskov替换原则:类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
放在抽象类中并不是一个好主意。一个实现细节应该像这样漏出来吗?可能不是。即使需要,你真的必须替换完整的地图吗?如果没有,您可以使用val
。或者,您可以使用def
构建一个用于添加,删除,查询元素的外观,而不在A
中提及地图。