Я хочу, чтобы функция принимала любое число (Int, Float, Double,...) в Swift
func myFunction <T : "What to put here"> (number : T) -> {
//...
}
без использования NSNumber
Я хочу, чтобы функция принимала любое число (Int, Float, Double,...) в Swift
func myFunction <T : "What to put here"> (number : T) -> {
//...
}
без использования NSNumber
Это действительно невозможно из коробки в Swift. Для этого вам нужно создать новый протокол, объявленный любыми методами и операторами, которые вы собираетесь использовать в своей общей функции. Этот процесс будет работать для вас, но точные детали будут зависеть от того, что делает ваша общая функция. Вот как вы это сделаете для функции, которая получает число n
и возвращает (n - 1)^2
.
Сначала определите свой протокол с операторами и инициализатором, который принимает Int
(чтобы мы могли вычесть его).
protocol NumericType {
func +(lhs: Self, rhs: Self) -> Self
func -(lhs: Self, rhs: Self) -> Self
func *(lhs: Self, rhs: Self) -> Self
func /(lhs: Self, rhs: Self) -> Self
func %(lhs: Self, rhs: Self) -> Self
init(_ v: Int)
}
Все числовые типы уже реализуют их, но на данный момент компилятор не знает, что они соответствуют новому протоколу NumericType
. Вы должны сделать это явным - Apple называет это "объявлением принятия протокола с расширением". Мы сделаем это для Double
, Float
и всех целых типов:
extension Double : NumericType { }
extension Float : NumericType { }
extension Int : NumericType { }
extension Int8 : NumericType { }
extension Int16 : NumericType { }
extension Int32 : NumericType { }
extension Int64 : NumericType { }
extension UInt : NumericType { }
extension UInt8 : NumericType { }
extension UInt16 : NumericType { }
extension UInt32 : NumericType { }
extension UInt64 : NumericType { }
Теперь мы можем написать нашу фактическую функцию, используя протокол NumericType
в качестве общего ограничения.
func minusOneSquared<T : NumericType> (number : T) -> T {
let minusOne = number - T(1)
return minusOne * minusOne
}
minusOneSquared(5) // 16
minusOneSquared(2.3) // 1.69
minusOneSquared(2 as UInt64) // 1
В качестве пояснения, касающегося комментария комментария, и для тех, кто не знает протоколы Swift, очень хорошо, дело здесь в том, что методы, объявленные в числовом типе, уже реализованы каждым из типов, для которых было объявлено о соответствии. Например, поскольку тип Int уже реализует...
func +(lhs: Self, rhs: Self) -> Self
... в протоколе NumericType не требуются дальнейшие детали реализации.
Цель объявления протокола в этом случае - не добавлять новые методы к любому из его типов реализации, а предоставлять единый фасад, который позволяет компилятору знать, что все, что реализует NumericType, поддерживает полный набор математических операторов Swift, Поскольку каждый из типов, которые добавили к ним добавление NumericType, уже реализует все методы в NumericType, все, что необходимо для их полного соответствия протоколу, состоит в том, чтобы объявить, что они соответствуют...
extension Int : NumericType { }
Как работает следующий протокол? Где реализации?
Согласно документу
"Протокол определяет схему методов, свойств и других требований, которые соответствуют конкретной задаче или функциональности".
protocol NumericType {
func +(lhs: Self, rhs: Self) -> Self
func -(lhs: Self, rhs: Self) -> Self
func *(lhs: Self, rhs: Self) -> Self
func /(lhs: Self, rhs: Self) -> Self
func %(lhs: Self, rhs: Self) -> Self
init(_ v: Int)
}