[Swift]扩展

来源:互联网 发布:类似弹个车的软件 编辑:程序博客网 时间:2024/06/09 23:05

1. Swift扩展的概念以及重要性:

    1) 扩展的概念:是指向一个已有的类、结构体、枚举添加新的功能(属性、方法、下标等),但不需要修改这些类型的源代码甚至不需要拥有这些类型的源代码;

    2) 和继承的区别:首先扩展可以运用到不止类(还包括结构体和下标,甚至是Int、Double等基本类型,实际上这些基本类型也是用结构体来实现的);

其次,虽然可以通过继承在新的子类中添加更多的功能,但是继承机制比较复杂而有时作者会限制类的继承(比如使用final声明等),但是扩展不受这些约束(比如一个类被声明为final的,虽然其不可被继承,但是仍然可以对其进行扩展):

final class A {    }extension A { // OK! 虽然不能继承但是仍能扩展    func f() {        println("haha")    }}
这里提一下扩展的语法:

extension 类名 {    扩展的内容...}
    3) 扩展的作用:

         i) 特别是在没有权限获取源代码的情况下也可以扩展类型,提高了逆向建模的能力;

         ii) 可以说扩展是一种轻量级的继承;

         iii) 在任何时候都要优先考虑使用扩展(一般Java程序员都会保守地选择继承),这是从简的编程原则,只有当扩展无法满足需求的时候再考略使用继承;

         iv) 扩展在Swift中地位非常重要,很多Swift API以及一些Swift的基本类型都是通过扩展实现的,比如String的很多方法就是通过扩展实现的;

    4) 可以对基本类型进行扩展,比如Int、String、Double、Character等,因为这些基本类型底层都是用结构体包装的!

    5) Swift允许扩展的内容:

         i) 对于值类型(结构体和枚举)可以扩展静态存储属性,但是对于类类型则不能扩展静态存储属性;

         ii) 对于任何类型都不能扩展实例存储属性;

         iii) 可以扩展计算属性(实例、静态都行);

         iv) 可以扩展方法(实例、静态都行);

         v) 可以扩展构造器;

         vi) 可以扩展下标;

         vii) 可以扩展嵌套类;

         viii) 可以扩展使其适配一个或多个协议;

    6) 扩展的最大亮点:在定义扩展后全局有效,即那些在扩展前定义的对象也可以使用扩展出的新功能;


2. 扩展静态存储属性:

    1) 只对于值类型成立;

    2) 举例:

extension Int {    static var sta_var = 90 // OK! Int是值类型的结构体}class A {    }//extension A {//    static var test = 11 // Bad! 不能扩展类类型的静态存储属性//}struct B {    }extension B {    static var test = 11 // OK! 结构体类型可以}enum C {    }extension C {    static var test = 22 // OK! 枚举类型也是值类型,同样也可以扩展静态存储属性}
    3) 但是对于任何类型都不能扩展实例存储属性!


3. 扩展计算属性:!注意值类型和枚举类型之间的区别

extension Int {    var errMessage: String { // 扩展实例的只读计算属性        switch self {        case -7: return "没有数据"        case -6: return "日期格式有误"        case -5: return "内容格式有误"        case -4: return "ID为空"        case -3: return "数据访问失败"        case -2: return "空间不足"        case -1: return "用户不存在"        default: return ""        }    }}println((-3).errMessage) // 数据访问失败,注意使用括号否则编译解析会有问题struct A {    }extension A {    static var x = 10 // 扩展静态存储属性    var y: Int { // 扩展实例可读可写计算属性对静态存储属性进行维护        get {            return A.x        }        set {            A.x = newValue        }    }}println(A.x) // 10var a = A()println(a.y) // 10a.y = 30println(A.x) // 30extension Double { // 模拟单位表示法    var km: Double { return self * 1_000.0 }    var m: Double { return self }    var cm: Double { return self / 100.0 }    var mm: Double { return self / 1_000.0 }}var some_km = 5.0.kmvar some_m = 3.9.mvar some_cm = 90.3.cmvar some_mm = 33.23.mmprintln(some_km) // 5000.0println(some_m) // 3.9println(some_cm) // 0.903println(some_mm) // 0.03323class B {    }extension B {    class var test: Int { // 扩展静态计算属性        return 23    }}

4. 扩展构造器:

对于结构体可以扩展普通构造器和代理构造器,但是对于类只能扩展便利构造器但不能扩展指定构造器!

struct A {    var a = 15    var b = 20        init(a: Int, b: Int) {        self.a = a        self.b = b    }}extension A { // 对于结构体既可以扩展普通构造器也可以扩展代理构造器    init(a: Int) {        self.a = a    }        init() {        self.init(a: 23, b: 88)    }}extension A { // 可以连续扩展任意多次    init(s: String) {        self.init()    }}class B {    var a: Int    var b: Int        init(a: Int, b: Int) {        self.a = a        self.b = b    }}extension B { // 对于类只能扩展便利构造器不能扩展指定构造器,否则会报错!    // !由于类只能扩展便利构造器而不能扩展指定构造器,因此就不能用super调用父类构造器了!    convenience init() {        self.init(a: 10, b: 20)    }}


5. 扩展方法:

按照之前讲过的定义方法的规则可以随意扩展:

extension Double {    static let rate = 3.773 // 结构体可以扩展静态存储结构        func getTotal() -> Double { // 扩展实例方法        return Double.rate * self    }        static func computeTotal(amount: Double) -> Double { // 扩展静态方法        return rate * amount    }        mutating func doubleIt() { // 要改变结构体本身的内容需要变异!        self = self * 2    }}class A { // 注意!类只支持静态计算属性不支持静态存储属性    var value: Double = 234.32}// 相应的类类型的版本extension A {    class var rate: Double {        return 3.231    }        func getTotal() -> Double {        return value * A.rate    }        class func computeTotal(amount: Double) -> Double {        return rate * amount    }        func doubleIt() {        value = value * 2    }}
一个扩展方法的非常有趣的例子:为Int扩展一个方法,使用Int的数值n重复n次动作,这个动作作为闭包作为参数传入扩展的方法

extension Int {    func rep(task: () -> ()) {        for _ in 0..<self {            task()        }    }}3.rep { println("haha") }


6. 扩展下标:

就跟普通定义下标一样,这里介绍两个扩展String和Int下标的有趣的例子:

扩展String下标,用来模仿C语言字符数组随机访问的功能

extension String {    subscript(index: Int) -> String { // 返回的字符用String包装        if index < 0 || index + 1 > countElements(self) {            return ""        }                var i = 0        for char in self { // 从字符串中取出的元素是Character类型的            if i == index {                return String(char) // 需要包装成String类型            }            i++        }                return ""    }}println("abc"[2]) // c
扩展Int下标,获得从低到高的第n位数字,第0位是最低位:

extension Int {    subscript(index: Int) -> Int {        var base = 1        for _ in 0..<index {            base *= 10        }                return (self / base) % 10    }}println(23423[2]) // 4


6. 扩展嵌套类型:

就和定义普通的嵌套类型一样,这里介绍一下在Character中扩展一个枚举类型,用于对字符的类型进行分类(元音、辅音等):

extension Character {    enum Kind: String {        case Vowel = "Vowel"        case Consonant = "Consonant"        case Other = "Other"    }        var kind: Kind {        switch String(self).lowercaseString {        case "a", "e", "i", "o", "u": return .Vowel        case "b", "c", "d", "f", "g": return .Consonant        default: return .Other        }    }}println(Character("I").kind.rawValue) // Vowel


7. 扩展适配协议:

可以扩展一个类型使其匹配一个或多个协议,这里只介绍其语法:

extension Type: Protocol1, Protocol2... {    ...}

0 0
原创粉丝点击