为什么我不能在Swift中使用泛型的子类? [英] Why can't I use a subclass of a generic type in Swift?

查看:105
本文介绍了为什么我不能在Swift中使用泛型的子类?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

为什么Swift不允许我将值Foo<U>分配给类型为Foo<T>的变量,其中U是T的子类?

Why doesn't Swift allow me to assign value Foo<U> to a variable of type Foo<T>, where U is a subclass of T?

例如:

class Cheese {
    let smell: Int
    let hardness: Int
    let name: String

    init(smell: Int, hardness: Int, name: String) {
        self.smell = smell
        self.hardness = hardness
        self.name = name
    }

    func cut() {
        print("Peeyoo!")
    }
}

class Gouda: Cheese {
    let aged: Bool

    init(smell: Int, hardness: Int, name: String, aged: Bool) {
        self.aged = aged
        super.init(smell: smell, hardness: hardness, name: name)
    }

    override func cut() {
        print("Smells delicious")
    }
}

class Platter<Food> {
    var food: Food

    init(food: Food) {
        self.food = food
    }
}

let goudaCheese = Gouda(smell: 6, hardness: 5, name: "Gouda", aged: false)
let goudaPlatter = Platter(food: goudaCheese)  //Platter<Gouda>

//error: cannot assign value of type 'Platter<Gouda>' to type 'Platter<Cheese>'
let platter: Platter<Cheese> = goudaPlatter

但是为什么不起作用?您可以为变量分配一个属于其类型的子类的对象,例如

But why doesn't it work? You can assign to a variable an object that's a subclass of it's type, e.g.

let gouda = Gouda(smell: 6, hardness: 5, name: "Gouda", aged: false)
let cheese: Cheese = gouda

您可以将子类添加到集合中

And you can add subclasses to collections:

let plainCheese = Cheese(smell: 2, hardness: 5, name: "American")
let gouda = Gouda(smell: 6, hardness: 5, name: "Gouda", aged: false)
var cheeses: [Cheese] = [plainCheese]
cheeses.append(gouda)

那么let platter: Platter<Cheese> = goudaPlatter有何不同?在任何情况下,如果可行,那将是不安全的?这仅仅是对Swift当前版本的限制吗?

So how is let platter: Platter<Cheese> = goudaPlatter different? Are there any circumstances where it would be unsafe if it worked? Is it simply a limitation of the current version of Swift?

推荐答案

您可以使用称为类型擦除.基本上,您创建一个包装"结构,该结构从泛型中隐藏了基础类的详细信息.这不是理想的方法,但是它可以让您完成与您尝试执行的操作类似的操作.

You can work around this using a technique called type erasure. Basically you create a "wrapper" struct which hides the underlying class detail from the generic. It's not ideal, but it allows you to accomplish something similar to what you're trying to do.

class Cheese {
    func doSomethingCheesy() {
        print("I'm cheese")
    }
}

class Gouda: Cheese {
    override func doSomethingCheesy() {
        print("I'm gouda")
    }
}

struct AnyCheese {
    let cheese: Cheese
}

class Container<T> {
    init(object: T) {
        self.object = object
    }
    let object: T
}

let cheese = Cheese()
let cheeseContainer: Container<AnyCheese> = Container(object: AnyCheese(cheese: cheese))

let gouda = Gouda()
let goudaContainer: Container<AnyCheese> = Container(object: AnyCheese(cheese: gouda))

cheeseContainer.object.cheese.doSomethingCheesy() // prints "I'm cheese"
goudaContainer.object.cheese.doSomethingCheesy()  // prints "I'm gouda"

这篇关于为什么我不能在Swift中使用泛型的子类?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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