美文网首页
Swift5.1学习随笔之扩展(Extension)

Swift5.1学习随笔之扩展(Extension)

作者: SAW_ | 来源:发表于2020-05-13 15:21 被阅读0次
    • Swift中的扩展,类似于OC中的分类Category
    • 扩展可以为枚举、类、结构体、协议添加新功能
      1. 可以添加方法、计算属性、下标、(便捷)初始化器、嵌套类型、协议等等
    • 扩展不能办到的事情
      1. 不能覆盖原有的功能
      2. 不能添加存储属性,不能向已有的属性添加属性观察器
      3. 不能添加父类
      4. 不能添加指定初始化器,不能添加反初始化器
      5. ......

    例子🌰:为Double类型增加扩展,新增只读的计算属性,计算属性本质是方法,相当于为Double新增方法

    extension Double {
        var second: Double { self }
        var minute: Double { self / 60.0 }
        var hour: Double { self / 3600.0 }
    }
    
    var s = 1200.0 //秒
    print(s.second) // 1200.0秒
    print(s.minute) // 20.0分钟
    print(s.hour) // 0.3333333333333333小时
    print(3600.0.minute) //60.0分钟
    

    数组Array本身不提供下标判断,因此不小心容易造成数组越界,导致程序奔溃。

    var arr = [10, 20, 30]
    var age = arr[-1] //运行报错,数组越界
    var age2 = arr[10] //运行报错,数组越界
    

    为数组Array扩展一个下标,实现下标判断,如果越界,就返回nil

    extension Array {
        subscript(nullable idx: Int) -> Element? {
            if (startIndex..<endIndex).contains(idx) {
                return self[idx]
            }
            return nil
        }
    }
    
    var arr = [10, 20, 30]
    var age = arr[nullable: -1]
    print(age as Any) // nil
    

    为类型Int扩展了一系列实现

    extension Int {
        //声明一个调用多次实现外部传入函数的扩展
        func repeats(task: () -> Void) {
            for _ in 0..<self {
                task()
            }
        }
        //实现平方计算
        mutating func square() -> Int {
            self = self * self
            return self
        }
        //嵌套一个enum枚举
        enum Kind {
            case negative, zero, positive
        }
        //增加计算属性,判断正数、负数、0
        var kind: Kind {
            switch self {
            case 0:
                return .zero
            case let x where x > 0:
                return .positive
            default:
                return .negative
            }
        }
        //声明一个下标,获取指定位数的数字
        subscript(digitIndex: Int) -> Int {
            var decimalBase = 1
            for _ in 0..<digitIndex {
                decimalBase *= 10
            }
            return (self / decimalBase) % 10
        }
    }
    
    3.repeats {
        print("lalalalla")
    }
    
    var number = 4
    print(number.square()) // 16
    
    print(Int.Kind.negative) // negative
    
    print(5.kind) // positive
    print(0.kind) // zero
    print((-5).kind) // negative
    
    var number2 = 123
    print(number2[0]) // 3
    print(number2[1]) // 2
    print(number2[2]) // 1
    print(number2[4]) // 0
    

    Person类增加扩展,增加Equatable协议实现==判断方法,增加一个便捷初始化器

    class Person {
        var age: Int
        var name: String
        init(age: Int, name: String) {
            self.age = age
            self.name = name
        }
    }
    
    extension Person: Equatable {
        static func == (lhs: Person, rhs: Person) -> Bool {
            lhs.age == rhs.age && lhs.name == rhs.name
        }
        convenience init() {
            self.init(age: 0, name: "")
        }
    }
    

    为结构体Point添加扩展,增加一个初始化器

    struct Point {
        var x: Int = 0
        var y: Int = 0
    }
    
    extension Point {
        init(_ point: Point) {
            self.init(x: point.x, y: point.y)
        }
    }
    
    var p1 = Point()
    var p2 = Point(x: 10)
    var p3 = Point(y: 20)
    var p4 = Point(x: 10, y: 20)
    //上面4种初始化,都是编译器自动提供了
    
    //这是扩展的,允许传入一个Point变量进行初始化
    var p5 = Point(p4)
    

    如果一个类型已经实现了协议的所有要求,但是还没有声明它遵守了这个协议,可以通过扩展来实现遵守这个协议

    protocol TestProtocol {
        func test()
    }
    
    class TestClass {
        func test() {
            print("test")
        }
    }
    
    extension TestClass: TestProtocol {
        
    }
    

    为所有的整数扩展一个判断奇偶的方法:
    因为整数有````Int、``UIntUint8Uint16Uint32...如果只是单独的写一个方法,那就得考虑到传参的问题。
    我们这好到整数的共同点,它们都遵守BinaryInteger协议,因此可以对BinaryInteger协议进行扩展。

    extension BinaryInteger {
        func isOdd() -> Bool {
            self % 2 != 0
        }
    }
    
    print(8.isOdd()) // false
    print(11.isOdd()) // true
    print((-5).isOdd()) // true
    print((-4).isOdd()) // false
    print(UInt8(7).isOdd()) // true
    

    • 扩展可以给协议提供默认实现,也间接实现可选协议的效果
    • 扩展可以给协议补充协议中从未声明过的方法
    protocol TestProtocol {
        func test1()
    }
    
    extension TestProtocol {
        func test1() {
            print("TestProtocol - test1")
        }
        //给协议补充test2方法
        func test2() {
            print("TestProtocol - test2")
        }
    }
    
    class TestClass: TestProtocol {
        //内部不实现test1,并不会报错,因为在协议扩展中实现了
    }
    
    var cls = TestClass()
    cls.test2() //可以调用test2方法
    

    扩展里面依然可以使用原类型的泛型

    class Stack<E> {
        var elements = [E]()
        func push(_ element: E) {
            elements.append(element)
        }
        func pop() -> E {
            elements.removeLast()
        }
        func size() -> Int {
            elements.count
        }
    }
    
    extension Stack {
        func top() -> E {
            elements.last!
        }
    }
    

    符合条件才扩展

    extension Stack: Equatable where E : Equatable {
        static func == (lhs: Stack<E>, rhs: Stack<E>) -> Bool {
            lhs.elements == rhs.elements
        }
    }
    

    相关文章

      网友评论

          本文标题:Swift5.1学习随笔之扩展(Extension)

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