Swift 泛型向上推 [英] Swift Generics & Upcasting

查看:37
本文介绍了Swift 泛型向上推的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I've got a quick question regarding generics in Swift. The problem is I'm trying to store a variable that takes a generic as a parameter, but am unable to cast it up to the type it is restricted by. It's best explained in a short example:

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
    }
}

上面的代码产生错误:Cast from Thing to unrelated type Thing always failed"

它不应该永远失败,因为 T 被限制为 Foo 的子类吗?我一定误解了泛型在 Swift 中的工作方式,任何指导或帮助将不胜感激!

Shouldn't it never fail, since T is restricted to being a subclass of Foo? I must be misunderstanding the way generics work in Swift, any guidance or help would be much appreciated!

推荐答案

Swift 泛型不是协变的.也就是说,正是错误所说的:你不能自动说 Basket 是一种 Basket 是一种Fruit.这是有充分理由的.

Swift generics are not covariant. That is to say, exactly what the error says: you can't automatically say a Basket<Apple> is a kind of Basket<Fruit> even if Apple is a kind of Fruit. There is good reason for this.

考虑以下代码:

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())

如果Basket 被认为是Basket,这将是合法的代码,并且我被允许在一篮子苹果中添加一个橙子.

This would be legal code if Basket<Apple> were considered a Basket<Fruit>, and I'd be allowed to add an orange to a basket of apples.

这篇关于Swift 泛型向上推的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆