Ios 斯威夫特仿制药公司;向上投射
我有一个关于Swift中泛型的快速问题。问题是我试图存储一个以泛型作为参数的变量,但无法将其转换为它所受限制的类型。最好用一个简短的例子来解释:Ios 斯威夫特仿制药公司;向上投射,ios,swift,generics,Ios,Swift,Generics,我有一个关于Swift中泛型的快速问题。问题是我试图存储一个以泛型作为参数的变量,但无法将其转换为它所受限制的类型。最好用一个简短的例子来解释: class Foo { } class Thing<T: Foo> { func produceBar() -> Bar { return Bar(aThing: self as! Thing<Foo>) } } class Bar { var thing: Thing<F
class Foo { }
class Thing<T: Foo> {
func produceBar() -> Bar {
return Bar(aThing: self as! Thing<Foo>)
}
}
class Bar {
var thing: Thing<Foo>
init(var aThing: Thing<Foo>) {
self.thing = aThing
}
}
class Foo{}
阶级事务{
func produceBar()->Bar{
返回条(aThing:self as!Thing)
}
}
分类栏{
东西:东西
初始化(变量:Thing){
自我感觉
}
}
上面的代码产生错误:“从对象转换为不相关类型的对象总是失败”
既然t被限制为Foo的一个子类,它就不应该失败吗?我一定是误解了Swift中泛型的工作方式,任何指导或帮助都将不胜感激 Swift泛型不是协变的。也就是说,错误的意思是:你不能自动地说
篮子
是一种篮子
,即使苹果
是一种水果
。这是有充分理由的
考虑以下代码:
class Fruit {}
class Apple: Fruit {}
class Orange: Fruit {}
class Basket<T: Fruit> {
private var items: [T]
func add(item: T) {
items.append(item)
}
init() {}
}
func addItem<T: Fruit>(var basket: Basket<T>, item: T) {
basket.add(item)
}
let basket:Basket<Apple> = Basket()
addItem(basket as Basket<Fruit>, Orange())
类水果{}
苹果类:水果{}
橙色类:水果{}
班级篮{
专用var项目:[T]
功能添加(项目:T){
items.append(项目)
}
init(){}
}
功能附加项(变量篮子:篮子,项目:T){
篮子。添加(项目)
}
放篮:篮=篮()
附加项(篮子作为篮子,橙色())
如果
篮子
被视为篮子
,我可以在一篮苹果上加一个橘子,那么这就是法律法规。这是一个很好的观点,也是为什么我不能这样做的原因。非常感谢。你有什么建议,我怎样才能用大致相同的方式存储一个变量?有没有可能/合法的说法是var-aThing:Thing
?让applarray:Array=[Apple()]var-fruitArray=applarray-as-Array-fruitArray.append(Orange())
好!但是为什么会这样呢?applarray-as-Array
在本例中,会制作一个副本,将每个Apple
封装在一个协议容器中,因此furtarray
的布局与applarray
不同(并且不能将as
转换回[Apple]
)。这在as
中是一个非常不幸的歧义。在某些情况下,它是强制转换(即,它只是将一组字节重新解释为其他类型),但在其他情况下,它强制转换。这些确实应该有不同的语法,但它们在Swift中没有,我不确定我是否理解。您给出的示例在Swift中的工作方式完全相同(几乎逐字转换;C#和Swift有很多共同点):。C#确实有co-/contra-/in variance(添加在.NET4中),但是您给出的代码没有演示它。您在右侧显示的错误与出于相同原因在Swift中得到的错误完全相同。在C#和Swift中,Basket不是Basket的一个子类型。C#确实有使用方差的方法,但它们并不总是像Swift的隐式数组协方差那样安全。有关这方面的讨论,请参见。我不确定Swift是否会遵循C#的输入/输出系统进行协方差/反方差声明,或者它是否会遵循Scala更明确的系统,但我确实希望有一天它会像.NET那样添加一个方差系统(添加它需要.NET大约8年的时间;我不知道它需要多长时间)。