Swift 关于数字类型转换

2019-07-11  本文已影响0人  烟影很美

Swift中的类型强制转换方式如下:

let num:Int = 1
let res:CGFloat = CGFloat(num)

只要查看CGFloat类型的定义, 能看到如下代码:

public struct CGFloat {

    /// The native type used to store the CGFloat, which is Float on
    /// 32-bit architectures and Double on 64-bit architectures.
    public typealias NativeType = Double

    public init()

    /// Creates a new instance from the given value, rounded to the closest
    /// possible representation.
    ///
    /// - Parameter value: A floating-point value to be converted.
    public init(_ value: Float)

    /// Creates a new instance from the given value, rounded to the closest
    /// possible representation.
    ///
    /// - Parameter value: A floating-point value to be converted.
    public init(_ value: Double)

    /// Creates a new instance from the given value, rounded to the closest
    /// possible representation.
    ///
    /// - Parameter value: A floating-point value to be converted.
    public init(_ value: Float80)

    public init(_ value: CGFloat)

    /// The native value.
    public var native: CGFloat.NativeType
}

很明显, 所谓的类型装换其实就是一个构造器

Swift中的数字实际是结构体, 只不过基于面向协议的思想, 通过一些列如协议成功构造了各种类型, 下面是Int类型的协议层次结构:

numeric-int.png

图片来源: https://swiftunboxed.com/protocols/numeric/

现在, 有一个需求, 一个函数需要一个CGFloat类型的参数:

func funcName(_ value: CGFloat) {
  ......
}

为了调用方便, 我们可能会使用泛型, 如下:

func funcName<T>(_ value: T) {
  ......
}

但是这样做的问题就是, 函数内最终任然需要一个CGFloat类型的参数, 如果value的类型是数字类型我们还可以使用强转, 但如果是其他特别类型呢? 当然, 我们可以分别实现不同类型参数的方法, 即不使用泛型.

func funcName<T>(_ value: Int) {
  ......
}
func funcName<T>(_ value: Float) {
  ......
}

......

很明显, 上述办法很繁琐. 基于Swift面向协议的考虑, 所有的数字类型是不是都遵守了相同的协议且没有其他类型遵守. 并且CGFloat的构造器要接受遵守该协议的类型

答案是, 所有浮点型类型都遵守BinaryFloatingPoint, 所有整型都遵守BinaryInteger. 而两种类型CGFloat都支持其作为参数的初始化. 下面是实现代码:

func funcName<T:BinaryFloatingPoint>(_ value: T) {
  let num:CGFloat = CGFloat(value)
  ......
}

func funcName<T:BinaryInteger>(_ value: T) {
  let num:CGFloat = CGFloat(value)
  ......
}

对以上代码进行简单的测试:

let res0 = funcName(123)
let res1 = funcName(123.123)

let value0 = 123
let res2 = funcName(value)
let value1 = 123.123
let res3 = funcName(value)

let res4 = funcName("123")  // 编译不通过

总结: 这里的重点不是怎么找到这些类型都遵守了什么协议, 以上代码所解决的问题也并不是什么技术难题, 但是对体会Swift面向协议的思想, 灵活使用泛型都有帮助. 对Swift中各种协议感兴趣的同学也可以去仔细研究一下, 可以更好的理解Swift这门语言.

上一篇 下一篇

猜你喜欢

热点阅读