swift 函数可以返回符合相同协议的不同类型吗?

时间:2021-03-08 14:08:44

标签: swift generics opaque-types

例如,假设一家披萨店有两种不同类型的披萨:

struct SmallPizza {
    var radius: Int
}
struct LargePizza {
    var diameter: Int
}

假设他们想使用上述类型创建不同的比萨饼,两者都符合相同的协议。你会这样做:

protocol Pizza {
    associatedtype PizzaType

    var pizzaType: PizzaType { get set }
    var name: String { get set }
}

struct PizzaOne: Pizza {
    var pizzaType: SmallPizza
    var name: String
}

struct PizzaTwo: Pizza {
    var pizzaType: LargePizza
    var name: String
}

在此之前,一切都可以无缝运行。现在他们想创建一个 PizzaManager 来获取某个 ID 的披萨:

struct PizzaManager {
    let pizzaOne = PizzaOne(pizzaType: SmallPizza(radius: 5), name: "Margherita")
    let pizzaTwo = PizzaTwo(pizzaType: LargePizza(diameter: 30), name: "Quattro Formaggi")
    
    // This functions shows the concept I would like to achieve, also if it doesn't work.
    func getPizza(forID id: Int) -> Pizza {
        if id == 1 {
            return pizzaOne
        } else {
            return pizzaTwo
        }
    }
}

使用这种方法会引发一个错误,即 可以理解:Protocol 'Pizza' can only be used as a generic constraint because it has Self or associated type requirements

我尝试过的其他事情:

  • 使用泛型类型,如错误消息所示:func getPizza<T: Pizza>(forID: identifier) -> T {...}。这不会引发错误,但也不是解决方案,因为调用者需要指定确切的类型,如 let result: PizzaOne = pizzaManager.getPizza(forID: 1)。这不能解决问题,因为我不想指定实际类型。
  • 我非常想避免Any。如果我理解正确,使用 Any 也会在需要解包时将问题从函数转移到调用方。
  • 使用不透明的返回类型:func getPizza(forID: identifier) -> some Pizza {...}。它们实际上听起来像是一个完美的解决方案,但是不透明只允许一个单一返回类型(所以要么是 PizzaOne 要么是 PizzaTwo)。

问题:

我想从函数中返回 PizzaOne 或 PizzaTwo,因为它们是符合 Pizza 的“某种”类型。所以在那之后,只需访问 Pizza 协议定义的属性,从而包含在符合 Pizza 协议的类型中。

我很确定这不能用不透明的返回类型来完成,因为它们只允许返回一种类型。也许这也不是 Swift 的功能,或者我误解了什么? 有没有其他方法可以解决这个问题?

希望您在阅读比萨饼时不会太饿;)。任何帮助将不胜感激!

0 个答案:

没有答案