我有以下场景
class Human {}
class Child: Human {}
class Person<T: Human> {}
var people = [Person<Human>]()
people.append(Person<Child>())
Run Code Online (Sandbox Code Playgroud)
但是在线上people.append(Person<Child>())我收到了错误
cannot convert value of type 'Person<Child>' to expected argument type 'Person<Human>'
Run Code Online (Sandbox Code Playgroud)
做下面的工作(这似乎是一个相同的情况)真的很奇怪
var myArray = [Array<UIView>]()
myArray.append(Array<UIImageView>())
Run Code Online (Sandbox Code Playgroud)
有人会理解为什么一种方式有效而不是另一种方式?
实际上你并没有足够强烈地表达这个案子.限定:
class Human {}
class Child: Human {}
struct Holder<T> {}
Run Code Online (Sandbox Code Playgroud)
我使Holder成为一个结构,所以没有人可以指责我们作弊:Array是一个结构,Holder是一个结构.并且我在占位符上删除了约束,将所有内容都缩减为最简单的形式.
现在只需指定一个Child数组,其中包含一个Human数组:
var arr = Array<Human>()
arr = Array<Child>()
Run Code Online (Sandbox Code Playgroud)
精细.现在尝试使用持有人:
var holder = Holder<Human>()
holder = Holder<Child>() // error
Run Code Online (Sandbox Code Playgroud)
并行性现在看起来很完美:Array是一个结构,Holder是一个结构,我们所做的就是尝试多态分配.所以有什么问题?
正如您可能已经怀疑的那样,问题在于您不是Apple.Apple编写代码,因此他们可以将Array和类似类型定义为参数化类型的协变.但它不是该语言的自动特征 - 也就是说,对于泛型一般来说并非如此.特别是,对于您定义的类型,您无法做到这一点.
所以Apple的Array是协变的,但你的Holder(或Person)不是,并且没有任何东西允许你切换协方差.
您可以看到为什么 Array是协变的.这是一个非常特殊的案例.数组是对象的集合.Apple知道,例如,Child对象的数组实际上也是Human对象的数组,因为每个Child都是Human(多态).因此,他们已经为数组实现了协方差,以确保这一点.
但是对你的人或我的持有人没有这样的保证.斯威夫特不知道什么你打算与占位符T.其中一个代替你或许想到的情况下做的Holder<Child>其中一个Holder<Human>预计将是错误的.所以Apple没有在这个方向做出任何假设.
我应该补充一点,区分以下内容非常重要:
class Human {}
class Child: Human {}
struct Holder<T> {
let thing : T
}
let holder : Holder<Human> = Holder(thing:Child()) // fine
Run Code Online (Sandbox Code Playgroud)
这是合法的,但它与我们一直在谈论的内容毫无关系.这里只涉及一种通用类型:Holder<Human>.我们所做的就是将一个孩子分配到thing一个人类所在的地方.这是一种很好的老式非泛型多态性.但你仍然不能投下Holder<Human>下来到Holder<Child>,即使thing 是一个孩子,你仍然无法分配Holder<Child>,其中一个Holder<Human>预期.
| 归档时间: |
|
| 查看次数: |
60 次 |
| 最近记录: |