我想在Dictionary中存储从泛型类派生的类的实例;也就是说,Dictionary应该存储从这个泛型派生的任何类的实例。
这样的事情:
class ParentClass {}
class ChildClass: ParentClass {}
class GenericClass<T: ParentClass> {
var foo:T?
}
typealias DerivedClass = GenericClass<ChildClass>
class TestGenerics {
var dict: Dictionary<String, GenericClass<**what goes here??**>> = [:]
func test() {
var derivedClassInstance = DerivedClass()
dict.updateValue(derivedClassInstance, forKey: "name")
}
}
这在Java中非常简单:
public class TestGenericsOuter {
class ParentClass {}
class ChildClass extends ParentClass {}
class GenericClass<T extends ParentClass> {
T foo;
}
class DerivedClass extends GenericClass<ChildClass> {}
class TestGenerics {
Dictionary<String, GenericClass<? extends ParentClass>> dict;
void test() {
DerivedClass derivedClassInstance = new DerivedClass();
dict.put("name", derivedClassInstance);
}
}
}
在Swift中这样的事情可能吗?我实现这一点的唯一方法是创建一个以“Any”作为值类型的Dictionary。但是,我失去了一些类型的安全性,所以如果可能的话,我想避免这种解决方案。
答案 0 :(得分:0)
我认为你不能模仿Java的通配符,但你可能也不需要。您可以在代码期望ChildClass
的任何地方使用ParentClass
。所以使用你的例子:
class TestGenerics {
var dict: Dictionary<String, GenericClass<ParentClass>> = [:]
func test() {
var derivedClassInstance = GenericClass<ParentClass>()
dict.updateValue(derivedClassInstance, forKey: "name")
}
}
现在只需使用ChildClass
填写foo
let test = TestGenerics()
test.test()
test.dict["name"]?.foo = ChildClass()
该代码编译没有错误。但是,Swift不支持自定义泛型类的协方差,因此您无法使用协变类型更改字典,因此以下内容无法编译:
test.dict = Dictionary<String, GenericClass<ChildClass>>()
//Error: 'ChildClass' is not identical to 'ParentClass'
这不是很直观,因为本机数组和字典确实支持协方差,所以这是允许的:
let array: Array<ParentClass> = Array<ChildClass>()
let dic: Dictionary<String, ParentClass> = Dictionary<String, ChildClass>()
但不是这样:
let generic: GenericClass<ParentClass> = GenericClass<ChildClass>()
//Error: 'ChildClass' is not identical to 'ParentClass'
基本上Swift将Array<ChildClass>
视为Array<ParentClass>
的子类型,但目前无法告诉编译器GenericClass<ChildClass>
是(或应该)GenericClass<ParentClass>
的子类型1}}。希望随着语言的发展,将添加一种将自定义类声明为协变的方法。
答案 1 :(得分:-1)
您需要参数化包含任何引用的类型,并在那里使用类型约束。此外,typealias与参数化类型的约束有关,因此它在该类型内部。
class ParentClass {}
class ChildClass: ParentClass {}
class GenericClass<T: ParentClass> {
var foo:T?
}
class TestGenerics<T: ParentClass> {
typealias DerivedClass = GenericClass<T>
var dict: Dictionary<String, GenericClass<T>> = [:]
func test() {
var derivedClassInstance = DerivedClass()
dict.updateValue(derivedClassInstance, forKey: "name")
}
}
let blah = TestGenerics<ChildClass>()
let baz = GenericClass<ChildClass>()
baz.foo = ChildClass()
blah.dict = ["a":baz]