swift简单总结(三十一)—— 扩展

版本记录

版本号 时间
V1.0 2017.08.01

前言

我是swift2.0的时候开始接触的,记得那时候还不是很稳定,公司的项目也都是用oc做的,并不对swift很重视,我自己学了一段时间,到现在swift3.0+已经出来了,自己平时也不写,忘记的也差不多了,正好项目这段时间已经上线了,不是很忙,我就可以每天总结一点了,希望对自己对大家有所帮助。在总结的时候我会对比oc进行说明,有代码的我会给出相关比对代码。
1. swift简单总结(一)—— 数据简单值和类型转换
2. swift简单总结(二)—— 简单值和控制流
3. swift简单总结(三)—— 循环控制和函数
4. swift简单总结(四)—— 函数和类
5. swift简单总结(五)—— 枚举和结构体
6. swift简单总结(六)—— 协议扩展与泛型
7. swift简单总结(七)—— 数据类型
8. swift简单总结(八)—— 别名、布尔值与元组
9. swift简单总结(九)—— 可选值和断言
10. swift简单总结(十)—— 运算符
11. swift简单总结(十一)—— 字符串和字符
12. swift简单总结(十二)—— 集合类型之数组
13. swift简单总结(十三)—— 集合类型之字典
14. swift简单总结(十四)—— 控制流
15. swift简单总结(十五)—— 控制转移语句
16. swift简单总结(十六)—— 函数
17. swift简单总结(十七)—— 闭包(Closures)
18. swift简单总结(十八)—— 枚举
19. swift简单总结(十九)—— 类和结构体
20. swift简单总结(二十)—— 属性
21. swift简单总结(二十一)—— 方法
22. swift简单总结(二十二)—— 下标脚本
23. swift简单总结(二十三)—— 继承
24. swift简单总结(二十四)—— 构造过程
25. swift简单总结(二十五)—— 构造过程
26. swift简单总结(二十六)—— 析构过程
27. swift简单总结(二十七)—— 自动引用计数
28. swift简单总结(二十八)—— 可选链
29. swift简单总结(二十九)—— 类型转换
30.swift简单总结(三十)—— 嵌套类型

扩展 - Extensions

扩展就是向一个已有的类、结构体或枚举类型添加新功能,这包括在没有权限获取原始源代码的情况下扩展类型的能力(即逆向建模),扩展和OC中的分类类似,不过不同的是,swift的扩展是没有名字的。

swift中的扩展可以:

  • 添加计算型属性和计算静态属性
  • 定义实例方法和类型方法
  • 提供新的构造器
  • 定义下标
  • 定义和使用新的嵌套类型
  • 使一个已有类型符合某个协议

注意:如果你定义了一个已有类型添加新功能,那么这个新功能对该类型的所有已有实例中都是可用的,即使他们是在你的这个扩展的前面定义的。

本篇主要从以下几个方面进行说明。

  • 扩展语法
  • 计算型属性
  • 构造器
  • 方法
  • 下标
  • 嵌套类型

扩展语法 - Extension Syntax

下面先看一下如何声明一个扩展。

extension SomeType {
    //加到SomeType的新功能代码
}

一个扩展可以扩展一个已有来行,使其能够适配一个或多个协议,当这种情况发生时,协议的名字应该完全按照类或结构体的名字方式进行书写。

extension SomeType : SomeProtocol, AnotherProtocol {
    //加到SomeType的新功能代码
}

按照这种方式添加的协议遵循者(protocol comformance)被称为在扩展中添加协议遵循者。


计算性属性 - Computed Properties

扩展可以向已有类型添加计算性实例属性和计算型类型属性,下面就是向swift内部的Double类型加入几个计算型实例属性。

下面看一下代码。

class JJPracticeVC: UIViewController {

    override func viewDidLoad()
    {
        super.viewDidLoad()

        view.backgroundColor = UIColor.lightGray
        
        let oneInch = 25.4.mm
        print("One inch is \(oneInch) meters")
        
        let threeFeet = 3.ft
        print("Three feet is \(threeFeet) meters")
    }
}

extension 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 ft : Double {
        return self/3.28084
    }
}

下面看输出结果

One inch is 0.0254 meters
Three feet is 0.914399970739201 meters

这些属性是只读的计算型属性,所以考虑他们不用get关键字,它们的返回值是Double类型。


构造器 - Initializers

扩展可以向已有类型添加新的构造器,这可以让你扩展其他类型,将你自己的定制类型作为构造参数,或者提供该类型的原始实现中没有包含的额外初始化选项。

扩展能向类中添加新的便利构造器,但是它们不能向类中添加新的指定构造器或析构函数,指定构造器和析构函数必须总是由原始的类实现来提供。

下面的例子给出的就是描述几何矩形的定制结构体Rect,下面看一下简单的代码。

struct Size {
    var width = 0.0, height = 0.0
}

struct Point {
    var x = 0.0, y = 0.0
}

struct Rect {
    var origin = Point()
    var size = Size()
}

因为结构体Rect提供了其所有属性的默认值,所以正如默认构造器中描述的,它可以自动接受一个默认的构造器和一个成员级构造器,这些构造器可以用于构造新的Rect实例。

let defaultRect = Rect()
let aRect = Rect(origin: Point(x : 2.0, y : 2.0 ), size: Size(width: 5.0, height: 5.0))

你可以提供一个额外的使用特殊中心点和大小的构造器来扩展Rect结构体。

extension Rect{
    init(center : Point, size : Size) {
        let originX = center.x - size.width * 0.5
        let originY = center.y - size.height * 0.5
        self.init(origin: Point(x : originX, y : originY), size: size)
    }
}

这个新的构造器首先根据提供的centersize值计算一个合适的点,然后调用该结构体自动的成员构造器init(origin: size:),该构造器将新的原点和大小存到了合适的属性中。

class JJPracticeVC: UIViewController {

    override func viewDidLoad()
    {
        super.viewDidLoad()

        view.backgroundColor = UIColor.lightGray
        
        let centerRect = Rect(center: Point(x : 4.0, y : 4.0), size: Size(width: 3.0, height: 3.0))
        print(centerRect)
    }
}

下面看输出结果

Rect(origin: JJSwift.Point(x: 2.5, y: 2.5), size: JJSwift.Size(width: 3.0, height: 3.0))

注意:如果你使用扩展提供了一个新的构造器,你依旧有责任保证构造过程能够让所有势力完全初始化。


方法 - Methods

扩展可以向已有类型添加新的实例方法和类型方法,下面的例子向Int类型添加一个新的实例方法repetitions

extension Int{
    func repetitions(task : () -> ())  {
        for i in 0..<self {
            task()
        }
    }
}

这个repetitions方法使用了一个() -> ()类型的单参数,表明函数没有参数而且没有返回值,定义该扩展后,你就可以对任意整数调用repetitions方法,进行多次执行某个任务。

下面我们就调用下试试。

class JJPracticeVC: UIViewController {

    override func viewDidLoad()
    {
        super.viewDidLoad()

        view.backgroundColor = UIColor.lightGray
        
        3.repetitions {
            print("Hello")
        }
    }
}

下面看输出结果

Hello
Hello
Hello

上面其实就是尾随闭包。

1. 修改实例方法 - Mutating Instance Methods

通过扩展添加的实例方法也可以修改该实例本身,结构体和枚举类型中修改self或其属性的方法必须将该实例方法标注为mutating,正如来自原始实现的修改方法一样。

下面的例子给Int类型添加了一个新的名字为square的修改方法,来实现一个原始值的平方计算。

class JJPracticeVC: UIViewController {

    override func viewDidLoad()
    {
        super.viewDidLoad()

        view.backgroundColor = UIColor.lightGray
        
        var someInt = 3
        someInt.square()
        print(someInt)
    }
}

extension Int{
    mutating func square(){
        self = self * self
    }
}

下面看输出结果

9

下标 - Subscripts

扩展可以向一个已有类型添加新下标,看下面的例子,向Int添加了一个整型下标,该下标[n]返回十进制数字从右向左的第n个数字。例如123456789[0]返回9

下面看一下代码。

class JJPracticeVC: UIViewController {

    override func viewDidLoad()
    {
        super.viewDidLoad()

        view.backgroundColor = UIColor.lightGray
        
        print(123456789[0])
    }
}

extension Int{
    subscript( digitIndex : Int) -> Int{
        var index = digitIndex
        var decimalBase = 1
        while index > 0 {
            decimalBase *= 10
            index -= 1
        }
        return (self/decimalBase) % 10
    }
}

下面看输出结果

9

如果该Int值没有足够的位数,下标越界,那么上述实现的下标会返回0,因为它会在数字左边自动补0

print(123456789[10])

下面看输出结果

0

嵌套类型 - Nested Types

扩展可以向已有的类、结构体和枚举添加新的嵌套类型。

extension Character{
    enum Kind {
        case Vowel, Consonaut, Other
    }
    
    var kind : Kind{
        switch String(self).lowercased() {
        case "a", "e", "i", "o", "u":
            return .Vowel
        case "b", "c", "d", "f", "g", "h", "j", "k", "l", "m","n", "p", "q", "r", "s", "t", "v", "w", "x", "y", "z":
            return .Consonaut
        default:
            return .Other
        }
    }
}

该例子向Character添加了新的嵌套枚举,这个名为kind的枚举表示特定字符的类型,这个例子还添加了一个新的计算实例属性kind,用来返回合适的kind枚举成员。

下面我们调用一下。

class JJPracticeVC: UIViewController {

    override func viewDidLoad()
    {
        super.viewDidLoad()

        view.backgroundColor = UIColor.lightGray
        
        printLetterKinds(word: "Hello")
    }
}

func printLetterKinds(word : String){
    print("\(word) is made up of the following kinds of letters")
    for character in word.characters {
        switch character.kind {
        case .Vowel:
            print("vowel")
        case .Consonaut:
            print("consonaut")
        default:
            print("other")
        }
    }
}

下面看输出结果

Hello is made up of the following kinds of letters
consonaut
vowel
consonaut
consonaut
vowel

这个很好理解,相信大家都可以看的明白。

后记

未完,待续~~~

山水之乐
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,117评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,328评论 1 293
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,839评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,007评论 0 206
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,384评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,629评论 1 219
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,880评论 2 313
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,593评论 0 198
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,313评论 1 243
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,575评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,066评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,392评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,052评论 3 236
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,082评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,844评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,662评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,575评论 2 270

推荐阅读更多精彩内容