其实你没有足够强调。定义:
class Human {}
class Child: Human {}
struct Holder<T> {}
我做了一个支架结构,所以没有人可以指责我们欺骗:数组是一个结构,持有人是一个结构。我取消了对占位符的限制,将所有内容都缩小为最简单的形式。
现在只需指定儿童的数组,其中人类的阵列预计:
var arr = Array<Human>()
arr = Array<Child>()
精细。现在,随着持有人尝试:
var holder = Holder<Human>()
holder = Holder<Child>() // error
的并行现在看起来完美:数组是一个结构,持有人是一个结构,而我们正在做的是想多态分配。所以有什么问题?
正如您可能已经怀疑的那样,问题在于您不是Apple。 Apple编写代码,因此他们可以在参数化类型上定义Array和类似covariant。但它不是该语言的自动功能 - 也就是说,对于泛型,一般并非如此。并且特别是你不会那样做你定义。
所以Apple的数组是协变的,但是你的Holder(或Person)不是,并且没有什么能让你切换协方差。
你可以看到为什么数组是协变的。这是一个非常特殊的情况。数组是对象的集合。 Apple知道一个例如Child对象的数组实际上也是一个Human对象的数组,因为每个Child都是一个Human(多态)。所以他们已经实现了数组的协方差,以确保这一点。
但是对于您的人或我的持有人没有这样的保证。 Swift不知道你打算如何用占位符T做什么。您可以考虑使用Holder<Child>
代替Holder<Human>
的情况,这可能是错误。所以苹果公司在这方面不做任何假设。
我要补充,这区分下列事项:
class Human {}
class Child: Human {}
struct Holder<T> {
let thing : T
}
let holder : Holder<Human> = Holder(thing:Child()) // fine
这是合法的,但它没有任何关系与我们一直在谈论。这里只涉及一种泛型:Holder<Human>
。我们正在做的是将一个孩子分配到thing
,其中一个人是预期的。这是非常老式的非泛型多态。但你仍然无法投出Holder<Human>
下降到Holder<Child>
,即使thing
是一个孩子,你仍然无法分配Holder<Child>
其中Holder<Human>
预期。
并且看到这个关于这个话题的经典文章:http://nomothetis.svbtle.com/type-variance-in-swift – matt