美文网首页
Swift 关于数字类型转换

Swift 关于数字类型转换

作者: 烟影很美 | 来源:发表于2019-07-11 16:09 被阅读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这门语言.

    相关文章

      网友评论

          本文标题:Swift 关于数字类型转换

          本文链接:https://www.haomeiwen.com/subject/dmhdkctx.html