generics - Swift:使用通配符作为泛型类型参数

标签 generics swift wildcard

我想将从通用类型派生的类的实例存储在字典中;也就是说,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”作为值类型的字典。但是,我失去了一些类型安全性,所以我想尽可能避免这种解决方案。

最佳答案

我认为您无法模仿 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> 的子类型.希望随着语言的发展,将添加一种将自定义类声明为协变的方法。

关于generics - Swift:使用通配符作为泛型类型参数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25273260/

相关文章:

java - 任何类型泛型构造的枚举类

ios - 快速获取屏幕截图(相册)计数

ios - UIPageViewController冲突问题

herokuapp.com 上的 heroku 子域通配符

c# - 为什么这个泛型方法要求 T 有一个公共(public)的、无参数的构造函数?

c# - 使用反射循环 IEnumerable<> 中的值

c++ - 我真的是返回地址或引用临时

ios - 在 Swift 中,如何从 dispatch_time_t 获取 NSDate?

PHP 比较两个字符串中的一个字符不同,通配符方法

java - 如何在类路径中使用通配符来添加多个 jar?