有没有办法将任何通用数值转换成Double?

时间:2018-12-14 00:16:05

标签: swift generics

所以我有一个方法,其中包含3种不同类型的参数:

Int32IntDouble。因此,想法是使用泛型来最小化接口

func resetProgressBarChunks<T:Numeric>(originalIterationCount: T) {
    guard let iCount = originalIterationCount as? Double else {return}

但是我已经意识到,在运行时,Int32Int参数实际上会使guard let失败。这是有道理的,只是我的一厢情愿。

但是,如果我尝试将Numeric简单地转换为双精度,编译器将发出吠叫:

func resetProgressBarChunks<T:Numeric>(originalIterationCount: T) {
    guard let iCount = Double(originalIterationCount) else {return}
  

不能为类型为'(T)'的参数调用类型为'Double'的初始化程序

我认为这也是有道理的,因为没有Double的初始化程序需要泛型。

所以看来我将被迫编写具有不同参数类型的3种方法。 Int32Int参数类型将只转换为Double,然后调用Double方法。这真的是最好的方法吗?我真的希望我可以以某种方式利用Numeric

2 个答案:

答案 0 :(得分:6)

仅出于句法说明的目的,这里有一个示例,使它成为泛型并针对所有三种类型都达到Double:

func f<T:Numeric>(_ i: T) {
    var d = 0.0
    switch i {
    case let ii as Int:
        d = Double(ii)
    case let ii as Int32:
        d = Double(ii)
    case let ii as Double:
        d = ii
    default:
        fatalError("oops")
    }
    print(d)
}

但是,这是否比重载更好?在我看来,重载要好得多,因为有了泛型,我们就让一堆不需要的类型进入了门。数字合同是谎言。 Double,Int和Int32的三重过载集会使编译器成为事实的来源。

答案 1 :(得分:4)

  

...,因为没有Double的初始化程序需要泛型。

那不是完全正确的。没有带有Numeric参数的初始化程序。但是有些通用的初始化程序带有BinaryIntegerBinaryFloatingPoint参数,所以两个重载就足够了:

func resetProgressBarChunks<T: BinaryInteger>(originalIterationCount: T) {
    let iCount = Double(originalIterationCount)
    // ...
}

func resetProgressBarChunks<T: BinaryFloatingPoint>(originalIterationCount: T) {
    let iCount = Double(originalIterationCount)
    // ...
}

这涵盖了DoubleIntInt32参数以及Float和所有其他固定大小的整数类型。