实现generics的自定义类的数组,不允许具有子类通用的自定义类

我有以下情况

class Human {} class Child: Human {} class Person {} var people = [Person]() people.append(Person()) 

但就行了people.append(Person())我收到错误了

 cannot convert value of type 'Person' to expected argument type 'Person' 

做以下工作真的很奇怪(这似乎是一个相同的情况)

 var myArray = [Array]() myArray.append(Array()) 

有人会理解为什么一种方式有效而不是另一种方式?

实际上你并没有足够强烈地表达这个案子。 定义:

 class Human {} class Child: Human {} struct Holder {} 

我使Holder成为一个结构,所以没有人可以指责我们作弊:Array是一个结构,Holder是一个结构。 并且我在占位符上删除了约束,将所有内容减少到最简单的forms。

现在只需指定一个Child数组,其中包含一个Human数组:

 var arr = Array() arr = Array() 

精细。 现在尝试使用持有人:

 var holder = Holder() holder = Holder() // error 

并行性现在看起来很完美:Array是一个结构,Holder是一个结构,我们所做的就是尝试多态分配。 所以有什么问题?

正如您可能已经怀疑的那样,问题在于您不是Apple。 Apple编写代码,因此他们可以将Array和类似的类型定义为参数化类型的协变 。 但它不是该语言的自动特征 – 也就是说,对于generics一般来说并非如此。 特别是,对于定义的类型, 无法做到这一点。

所以Apple的Array是协变的,但你的Holder(或Person)不是,并且没有任何东西允许你切换协方差。

你可以看到为什么 Array是协变的。 这是一个非常特殊的案例。 数组是对象的集合。 Apple知道,例如,Child对象的数组实际上也是Human对象的数组,因为每个Child都是Human(多态)。 因此,他们已经为数组实现了协方差,以确保这样做。

但是对于你的人或我的持有人没有这样的保证。 Swift不知道你打算用占位符T做什么 。你可以想到用一个Holder取代Holder 所谓的 错误的情况 。 所以Apple没有在这个方向做出任何假设。


我应该补充说,区分以下内容很重要:

 class Human {} class Child: Human {} struct Holder { let thing : T } let holder : Holder = Holder(thing:Child()) // fine 

这是合法的,但它与我们一直在谈论的内容毫无关系。 这里只涉及一种通用类型: Holder 。 我们所做的就是将一个孩子分配到一个人类所需的thing中。 这是一种很好的老式非generics多态性。 但是你仍然无法将Holder投下一个Holder Holder ,即使thing 一个孩子,你仍然不能指定一个HolderHolder