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

iel*_*ani 36 double int numbers swift

我想在Swift中创建一个函数接受任何数字(Int,Float,Double,...)

func myFunction <T : "What to put here"> (number : T) ->  {
    //...
}
Run Code Online (Sandbox Code Playgroud)

不使用NSNumber

Nat*_*ook 51

更新:下面的答案原则上仍然适用,但Swift 4完成了数字协议的重新设计,因此添加自己的协议通常是不必要的.在构建自己的系统之前,请先查看标准库的数字协议.


这实际上不可能在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)
}
Run Code Online (Sandbox Code Playgroud)

所有数值类型都已实现这些,但此时编译器不知道它们符合新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 { }
Run Code Online (Sandbox Code Playgroud)

现在我们可以使用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
Run Code Online (Sandbox Code Playgroud)

  • 谢谢,这么棒的答案! (2认同)
  • 有了这种方法,有没有办法将`T`转换为`Int`?就像`Int(数字)`?或者使用其他功能,如`floor(number)`? (2认同)