声明扩展的语法格式如下:

extension 类型名 {

//添加新功能

}

声明扩展的关键字是extension,“类型名”是Swift中已有的类型,包括类、结构体和枚举,但是我们仍然可以扩展整型、浮点型、布尔型、字符串等基本数据类型,这是因为这些类型本质上也是结构体类型。打开Int的定义如下:

  1. struct Int : SignedInteger {
  2. init()
  3. init(_ value: Int)
  4. static func convertFromIntegerLiteral(value: Int) -> Int
  5. typealias ArrayBoundType = Int
  6. func getArrayBoundValue() -> Int
  7. static var max: Int { get }
  8. static var min: Int { get }
  9. }

从定义可见Int是结构体类型。不仅是Int类型,我们熟悉的整型、浮点型、布尔型、字符串等数据类型本质上都是结构体类型。

Swift中的扩展机制可以在原始类型中添加的新功能包括:

  • 实例计算属性和类型计算属性

  • 实例方法和类型方法

  • 构造函数

  • 下标

还有嵌套类型等内容也可以扩展,扩展还可以遵从协议。

===================================

可以在原始类型上扩展计算属性,包括实例计算属性和静态计算属性。添加计算属性的定义,与普通的计算属性的定义是一样的。

实例计算属性示例:在网络编程时,为了减少流量,从服务器端返回的不是信息描述,而是编码,然后在本地再将编码转换为描述信息。为此定义了如下Int类型扩展:

  1. extension Int {              //定义Int类型的扩展
  2. var errorMessage : String {   //只读计算属性
  3. var errorStr = ""
  4. switch (self) {
  5. case -7:
  6. errorStr = "没有数据。"
  7. case -6:
  8. errorStr = "日期没有输入。"
  9. case -5:
  10. errorStr = "内容没有输入。"
  11. case -4:
  12. errorStr = "ID没有输入。"
  13. case -3:
  14. errorStr = "据访问失败。"
  15. case -2:
  16. errorStr = "您的账号最多能插入10条数据。"
  17. case -1:
  18. errorStr = "用户不存在,请到http://51work6.com注册。"
  19. default:
  20. errorStr = ""
  21. }
  22. return errorStr
  23. }
  24. }
  25. let message = (-7).errorMessage      //获得-7编码对应的描述信息
  26. print("Error Code : -7 , Error Message : \(message)")

注意整个-7包括负号是一个完整的实例,因此调用它的属性时需要将-7作为一个整体用小括号括起来。然而,如果是7则不需要括号。

下面再看一个静态属性的示例:

  1. struct Account {             //定义Account结构体
  2. var amount : Double = 0.0               //账户金额
  3. var owner : String = ""                 //账户名
  4. }
  5. extension Account {          //定义Account结构体的扩展静态
  6. static var interestRate : Double {      //利率
  7. return 0.0668
  8. }
  9. }
  10. print(Account.interestRate)  //打印输出interestRate属性

打印输出interestRate属性,访问方式与其他的静态计算属性一样,通过“类型名”加“.”来访问静态计算属性。

扩展方法

可以在原始类型上扩展方法,包括实例方法和静态方法。这些添加方法的定义与普通方法的定义是一样的。

下面先看一个示例:

  1. extension Double {//定义Double类型的扩展
  2. static var interestRate : Double = 0.0668 //利率
  3. func interestBy1() -> Double {
  4. return self * Double.interestRate  //静态属性利率
  5. }
  6. mutating func interestBy2() {     //定义实例方法interestBy2
  7. self = self * Double.interestRate
  8. }
  9. static func interestBy3(amount : Double) -> Double {  //定义静态方法interestBy3
  10. return interestRate * amount       //返回值是计算利息结果
  11. }
  12. }
  13. let interest1 = (10_000.00).interestBy1()    //调用interestBy1方法计算利息
  14. print("利息1 : \(interest1)")
  15. var interest2 = 10_000.00    //调用interestBy2方法计算利息
  16. interest2.interestBy2()
  17. print("利息2 : \(interest2)")
  18. var interest3 = Double.interestBy3(10_000.00)    //调用interestBy3方法计算利息
  19. print("利息3 : \(interest3)")

代码self = self *Double.interestRate,把计算结果直接赋值给当前实例self。在结构体和枚举类型中给self赋值会有编译错误,需要在方法前面加上mutating关键字,表明这是变异方法。

调用interestBy1方法计算利息,调用它的实例10_000.00,它的返回值被赋值给interest1常量,这是很常见的调用过程。

调用interestBy2方法计算利息,我们不能使用10_000.00实例调用,而是需要一个Double类型的变量interest2。interestBy2是变异方法,它会直接改变变量interest2的值,因此interest2.interestBy2()语句调用完成后,变量interest2的值就改变了。

调用interestBy3方法计算利息,它是静态方法,调用它需要以“类型名.”的方式即“Double.”的方式调用。

=================================

扩展类型的时候,也可以添加新的构造函数。值类型与引用类型扩展有所区别。值类型包括了除类以外的其他类型,主要是枚举类型和结构体类型。

值类型扩展构造函数

扩展结构体类型中定义构造函数的示例:

  1. struct Rectangle {
  2. var width : Double
  3. var height : Double
  4. init(width : Double, height : Double) {
  5. self.width   = width
  6. self.height  = height
  7. }
  8. }
  9. extension Rectangle {        //定义了Rectangle的扩展类型
  10. init(length : Double) {
  11. self.init(width : length, height : length)
  12. }
  13. }
  14. var rect = Rectangle(width : 320.0, height : 480.0)  //调用两个参数的构造函数,这个构造函数是原始类型提供, Rectangle类型已经是扩展类型
  15. print("长方形:\(rect.width) x \(rect.height)")
  16. var square = Rectangle(length: 500.0)    //调用一个参数的构造函数,这个构造函数是扩展类型提供的
  17. print("正方形:\(square.width) x \(square.height)")

self.init是调用了原始类型的两个参数的构造函数。

引用类型扩展构造函数

扩展类中定义构造函数的示例:

  1. class Person {
  2. var name : String
  3. var age : Int
  4. func description() -> String {
  5. return "\(name) 年龄是: \(age)"
  6. }
  7. init (name : String, age : Int) {
  8. self.name = name
  9. self.age  = age
  10. }
  11. }
  12. extension Person {           //定义Person类的扩展类型
  13. convenience init (name : String) {    //便利构造函数
  14. self.init(name : name, age : 8)
  15. }
  16. }
  17. let p1 = Person(name : "Mary")   //调用两个参数的构造函数,这个构造函数是原始类型提供,这时候的Person类型已经是扩展类型。
  18. print("Person1 : \(p1.description())")
  19. let p2 = Person(name : "Tony", age : 28)// 调用一个参数的构造函数创建Person实例,这个构造函数是扩展类型提供的。
  20. print("Person2 : \(p2.description())")

代码self.init(name :name, age : 8)调用指定构造函数代理部分构造任务。

Swift—扩展声明-备的更多相关文章

  1. 《从零开始学Swift》学习笔记(Day 49)——扩展声明

    原创文章,欢迎转载.转载请注明:关东升的博客 声明扩展的语法格式如下: extension 类型名 { //添加新功能 } 声明扩展的关键字是extension,“类型名”是Swift中已有的类型,包 ...

  2. 【iOS】Swift扩展extension和协议protocol

    加上几个关节前Playground摘要码进入github在,凝视写了非常多,主要是为了方便自己的未来可以Fanfankan. Swift语法的主要部分几乎相同的. 当然也有通用的.运算符重载.ARC. ...

  3. Swift扩展

    Swift中的「扩展」(extensions)和OC中的categories类似,只是Swift中的「扩展」没有名字.Swift中的「扩展」可以向一个已有的类/结构体/枚举类型添加新功能,这包括在没有 ...

  4. 27.怎样在Swift中声明typedef?

    在OC中,我们经常会用typedef关键字来声明Block,例如: /** * 通用的空闭包类型,无参数,无返回值 */ typedef void (^GofVoidBlock)(void); 在Sw ...

  5. Swift扩展(Extension)

    在现有类和结构体的类型基础上,扩展新的功能. 语法: extension SomeType{ // new functionality to add to SomeType goes here } A ...

  6. Swift—属性观察者-备

    为了监听属性的变化,Swift提供了属性观察者.属性观察者能够监听存储属性的变化,即便变化前后的值相同,它们也能监听到. 属性观察者主要有以下两个: willSet:观察者在修改之前调用. didSe ...

  7. Swift 可选类型-备

    我们先看看如下代码: var n1: Int = 10 n1 = nil         //编译错误 let str: String = nil    //编译错误 Int和String类型不能接受 ...

  8. Swift 可选链-备

    在Swift程序表达式中会看到问号(?)和感叹号(!),它们代表什么含义呢?这些符号都与可选类型和可选链相关,下面来看看可选链. 可选链: 类图: 它们之间是典型的关联关系类图.这些类一般都是实体类, ...

  9. Swift中声明协议中的class关键字的作用

    大熊猫猪·侯佩原创或翻译作品.欢迎转载,转载请注明出处. 如果觉得写的不好请多提意见,如果觉得不错请多多支持点赞.谢谢! hopy ;) 最近在Cocos2D编程for Swift中看到以下一个代码片 ...

随机推荐

  1. 5. c++ 内存管理 C/C++ 内存机制

    参考自:http://blog.csdn.net/wpf_ml/article/details/7759911 1. 内存,Cache,寄存器内存:通常计算机将数据存放在物理内存,cache及寄存器中 ...

  2. 关于Cookie和Session【转载】

    当你第一次访问一个网站的时候,网站服务器会在响应头内加上Set-Cookie:PHPSESSID=nj1tvkclp3jh83olcn3191sjq3(php服务器),或Set-Cookie JSES ...

  3. 基于JAVA的webVNC

    jxpiInstall安装程序下载: http://sdlc-esd.sun.com/ESD6/JSCDL/jdk/7u60-b19/jxpiinstall.exe?AuthParam=1402208 ...

  4. Oracle Dataguard三种保护模式

    Oracle Dataguard提供了三种数据保护模式,在此分别总结一下三种数据保护模式的特点. 1.最大保护模式1)这种模式提供了最高级别的数据保护能力:2)要求至少一个物理备库收到重做日志后,主库 ...

  5. SqlServer中计算列详解

    计算列区别于需要我们手动或者程序给予赋值的列,它的值来源于该表中其它列的计算值.比如,一个表中包含有数量列Number与单价列Price,我们就可以创建计算列金额Amount来表示数量*单价的结果值, ...

  6. Highcharts下载与使用_数据报表图

    Highcharts简介 Highcharts:功能强大.开源.美观.图表丰富.兼容绝大多数浏览器的纯js图表库 Highcharts是一款纯javascript编写的图表库,能够很简单便捷的在Web ...

  7. jsp 常用9大内置对象

    |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| ...

  8. 告诉你LTE-FDD与LTE-TDD的区别

    [PConline 技术分析]移动早在去年已经拿下了TD-LTE的4G牌照,而中国联通与中国电信的FDD-LTE的牌照在近日正式拿下,而对于4G网络,有多少真正了解呢?接下来笔者就为大家解释一下4G的 ...

  9. linux怎么给一个普通用户reboot权限?

    分四种情况讨论:1.让任何人(包括根本不拥有系统帐号的人)都可以通过控制台reboot在/etc/inittab文件中保留ca::ctrlaltdel:/sbin/shutdown -t3 -r no ...

  10. struts2,hibernate,spring整合笔记(2)

    上一话struts2,hibernate,spring整合笔记(1) 接下来继续 配置完struts之后就要开始hibernate的配置 hibernate的环境并不依赖web开发环境,在我第一次配置 ...