无法分配泛型类型的值
Posted
技术标签:
【中文标题】无法分配泛型类型的值【英文标题】:Cannot assign value of generic type 【发布时间】:2016-12-26 08:03:59 【问题描述】:我有通用类 - Class1
。
class Class1<T>
我有 Class2
变量 object1
类型为 Class1
和泛型类型 UIView
class Class2
var object1: Class1<UIView>?
当我创建Class2
的实例并尝试分配给object1
类型Class1
和泛型类型UITableView
的实例时,我收到一个错误:“无法将Class1<UITableView>
类型的值分配给Class1<UIView>
类型"
var c = Class2()
c.object1 = Class1<UITableView>()
不过,同样的逻辑也适用于 Array。为什么?
【问题讨论】:
我认为Array
类型发生了一些编译器魔法。从技术上讲,Generic<Supertype>
与Generic<Subtype>
的类型不同,您不能将后者的值分配给前者的属性。但在数组的情况下,你可以看到它确实有效。
This answer 可能对您要查找的内容有用...
【参考方案1】:
让我详细说明安东的评论。问题是何时可以将 B 用于 A。通常,当 B 是 A 的子类型时,您可以这样做。例如,您可以将 UITableView
分配给 UIView
类型的变量。
那么什么时候是其他东西的子类型?
对于类,这很简单:如果您从A
继承B
,则B
是A
的子类型。
对于函数类型,您需要考虑参数类型和返回类型。如果F2
的参数类型是F1
的参数的超类型并且F2
的返回类型是F1
的返回的子类型,则函数类型F2
是函数类型F1
的子类型类型。你可以说一个函数不能要求更多(即它不能要求子类型作为参数但可以要求超类型)并且不能提供更少(即它不能返回超类型但可以返回子类型)以使其类型成为子类型.术语是参数类型必须是逆变,返回类型必须是协变。
例子:
var f1: UIControl -> UIControl = ...
let f2: UIView -> UIControl = ...
let f3: UIControl -> UIButton = ...
let f4: UIView -> UIButton = ...
f1 = f2 // Fine, f2 takes UIView so it also takes UIControl
f1 = f3 // Fine, f3 returns UIButton which is a UIControl
f1 = f4 // Fine, both of the above
let f5: UIButton -> UIControl
let f6: UIControl -> UIView
let f7: UIButton -> UIView
f1 = f5 // Error, couldn’t call with a UIControl because f5 demands at least a UIButton
f1 = f6 // Error, call would return only a UIView
f1 = f7 // Error, both of the above
所以f2
、f3
和f4
的类型是f1
类型的子类型,f5
、f6
和f7
的类型不是。
现在泛型类型呢?在 Swift 中,带有类型参数的自定义类型都是不变的。也就是说,在您的示例中,无论T1
和T2
之间的关系如何,都不能将Class1<T2>
对象用作Class1<T1>
对象(除非T1
和T2
是同一类型)。
然而,Swift 确实有一些内置的方差规则可以让你的数组示例工作:[UITableView]
(Array<UITableView>
) 是 [UIView]
(Array<UIView>
) 的子类型。请注意,选项也是如此,即UITableView?
(Optional<UITableView>
) 是UIView?
(Optional<UIView>
) 的子类型。所以数组和可选项都与它们的类型参数是协变的。
进一步阅读:
Liskov Substitution Principle on Wikipedia Mike Ash on Covariance and Contravariance【讨论】:
以上是关于无法分配泛型类型的值的主要内容,如果未能解决你的问题,请参考以下文章