Возврат двух типов из одной функции с использованием соответствия протокола

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'

Хотя ошибка имеет смысл, однако, я не понимаю, почему Double а также Int соответствуют этому типу, но не могут быть возвращены

1 ответ

Решение

Предположим, ваш метод компилируется,

Давайте создадим другой тип, который соответствует PriceCalculatable:

struct Foo : PriceCalculatable {}

Теперь попробуем вызвать ваш метод:

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

С точки зрения компилятора вышеприведенное компилируется, но это приводит к несогласованности во время выполнения. Как среда выполнения может преобразовать Double (finalPrice) в Foo?

Поэтому ваш метод не должен компилироваться.

Чтобы заставить его работать, вы можете создать ConvertileFromDouble протокол и сделать Int а также Double соответствовать этому. В протоколе необходимо указать инициализатор, который принимает 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 {
        ...
Другие вопросы по тегам