对于通用函数,什么协议应采用什么协议来将任何数字类型作为Swift中的参数?

时间:2014-08-29 20:09:20

标签: swift numbers int double

我想让函数接受Swift中的任何数字(Int,Float,Double,...)

func myFunction <T : "What to put here"> (number : T) ->  {
    //...
}

不使用NSNumber

2 个答案:

答案 0 :(得分:52)

更新:以下答案原则上仍然适用,但Swift 4完成了数字协议的重新设计,因此添加自己的协议通常是不必要的。在构建自己的系统之前,请先查看standard library's numeric protocols


这实际上不可能在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称之为“通过扩展声明协议采用”。我们将对DoubleFloat以及所有整数类型执行此操作:

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

答案 1 :(得分:0)

作为一个关于评论的澄清和那些不太了解Swift协议的说明,这里的要点是,在Numeric Type中声明的方法已经由声明了一致性的每个类型实现。例如,因为Int类型已经实现了......

func +(lhs: Self, rhs: Self) -> Self

... NumericType协议中不需要进一步的实现细节。

在这种情况下,协议声明的目的不是为其任何实现类型添加新方法,而是提供统一的外观,允许编译器知道实现NumericType的任何内容都支持完整的Swift数学运算符集。 。因为添加了NumericType一致性的每个类型已经实现了NumericType中的所有方法,所以它们完全符合协议所需要的就是声明它们符合......

extension Int : NumericType { }