使用协议一致性从一个函数返回两种类型

时间:2018-07-19 09:16:05

标签: swift generics swift-protocols

protocol PriceCalculatable {}
extension Int : PriceCalculatable {}
extension Double : PriceCalculatable {}


class PriceCalculator {
   static func culculateFinalPrice<T: PriceCalculatable>(for products: [Product],
                                applying coupon: Coupon?) -> T {

    let x = products.reduce(0) { price, product in
        return price + product.price
    }

    var finalPrice = Double(x)

    if let coupon = coupon {
        let multiplier = coupon.discountPercentage / 100
        let discount = Double(finalPrice) * Double(multiplier)
        finalPrice -= Double(discount)
    }

    return finalPrice
   }
}

我收到一条错误消息:

  

无法将类型为“ Double”的返回表达式转换为类型为“ T”

尽管该错误是有道理的,但我不理解为什么DoubleInt符合该类型却无法返回

1 个答案:

答案 0 :(得分:3)

假设您的方法可以编译,

让我们创建另一种符合PriceCalculatable的类型:

struct Foo : PriceCalculatable {}

现在,我们尝试调用您的方法:

let foo: Foo = PriceCalculator.culculateFinalPrice(for: someProducts, applying: myCoupon)

从编译器的角度来看,以上编译,但是这导致运行时不一致。运行时如何将DoublefinalPrice)转换为Foo

因此,您的方法不应编译。

要使其生效,您可以创建一个ConvertileFromDouble协议并使IntDouble符合该协议。在该协议中,您需要指定一个以Double作为参数的初始化程序。

protocol ConvertibleFromDouble {
    init(_ doubleValue: Double)
}

extension Int: ConvertibleFromDouble {

}

extension Double: ConvertibleFromDouble {

}

class PriceCalculator {
    static func culculateFinalPrice<T: ConvertibleFromDouble>(for products: [Product],
                                                          applying coupon: Coupon?) -> T {
        ...