Возврат двух типов из одной функции с использованием соответствия протокола
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 {
...