Ios 斯威夫特仿制药公司;向上投射

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

我有一个关于Swift中泛型的快速问题。问题是我试图存储一个以泛型作为参数的变量,但无法将其转换为它所受限制的类型。最好用一个简短的例子来解释:

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年的时间;我不知道它需要多长时间)。