Swift语法2.21(扩展)

本文参考了Swift2.2与3.0的语法,在少数地方添加了自我理解与示例.

扩展(Extensions)

扩展就是向一个已有类、结构体、枚举类型或者协议类型 添加新功能

这包括在没有权限获取原始源代码的情况下扩展类型的能力(即逆向建模)。

扩展Objective-C中的分类(categories)类似。
(不过与 Objective-C 不同的是,Swift 的扩展没有名字。)

Swift中的扩展可以:
添加计算型属性计算型静态属性
添加实例方法类型方法
添加新的构造器
添加下标
添加和使用新的嵌套类型
使一个已有类型符合某个协议
在 Swift 中,你甚至可以对一个协议(Protocol)进行扩展,
(你可以从协议扩展获取更多的细节。)

注意
扩展可以对 一个类型 添加新的功能,但是不能重写已有的功能

扩展语法(Extension Syntax)

声明一个扩展使用关键字extension
<pre>
<code>
extension SomeType { // 加到SomeType的新功能写到这里 }
</code>
</pre>

一个扩展可以扩展一个已有类型使其能够适配一个或多个协议(protocol)
<pre>
<code>
//SomeType类型遵循协议SomeProtocol, AnotherProctocol //SomeType类型是协议SomeProtocol, AnotherProctocol的成员 extension SomeType: SomeProtocol, AnotherProctocol { // 协议实现写到这里 }
</code>
</pre>

按照这种方式添加协议遵循者(protocol conformance)被称为在扩展中添加协议成员

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

计算型属性(Computed Properties)

扩展可以向已有类型添加计算型实例属性计算型类型属性
下面的例子向 Swift的内建Double类型 添加了5个计算型实例属性
<pre>
<code>
`
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 }
}

let aNumber = 3.1415
print(aNumber.km)
print(aNumber.m)
print(aNumber.cm)
print(aNumber.mm)
print(aNumber.ft)

//打印
//3141.5
//3.1415
//0.031415
//0.0031415
//0.957529169359067
`
</code>
</pre>

注意
扩展
可以添加新的计算属性
不可以添加存储属性
不可以向已有属性添加属性观测器(property observers)

构造器(Initializers)

扩展可以向已有类型 添加 新的构造器

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

注意

如果你使用扩展向 一个值类型 添加 一个构造器,该值类型 已经为所有的存储属性 提供了默认值,而且没有定义任何定制构造器(custom initializers)
你可以在值类型的 扩展构造器中 调用默认构造器(default initializers) 和 逐一成员构造器(memberwise initializers)

下面的例子定义了一个 用于描述几何矩形 的 结构体Rect
<pre>
<code>
`
//定义了两个 结构体Size和Point ,它们都把0.0作为所有属性的默认值:
struct Size
{
var width = 0.0, height = 0.0
}
struct Point
{
var x = 0.0, y = 0.0
}
//结构体Rect
struct Rect
{
var origin = Point()
var size = Size()
}
//在extension中提供一个使用center和size的构造器来扩展Rect结构体:
extension Rect
{
init(center: Point, size: Size)
{
let originX = center.x - (size.width / 2)
let originY = center.y - (size.height / 2)
//调用逐一成员构造器
self.init(origin: Point(x: originX, y: originY), size: size)
}
}
//因为结构体Rect提供了其所有属性的默认值,可以使用默认构造器和逐一成员构造器。这些构造器可以用于构造新的Rect实例:
let defaultRect = Rect()//使用默认构造器
let memberwiseRect = Rect(origin: Point(x: 2.0, y: 2.0),size: Size(width: 5.0, height: 5.0))//使用逐一成员构造器

//调用结构体Rect中新提供的构造器构造Rect实例
let centerRect = Rect(center: Point(x: 4.0, y: 4.0),size: Size(width: 3.0, height: 3.0))
`
</code>
</pre>

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

方法(Methods)

扩展可以向已有类型 添加新的 实例方法 和 类型方法
下面的例子为 Int类型 扩展添加 一个名为repetitions的新实例方法
<pre>
<code>
`
extension Int
{
//repetitions方法使用了一个参数,类型为 () -> () ,即没有参数没有返回值。
//任意整数可以调用repetitions方法,实现多次执行block
func repetitions(task: () -> ())
{ for _ in 0 ..< self { task() }
}
}

5.repetitions { print("hello world") }
//打印
//hello world
//hello world
//hello world
//hello world
//hello world

`
</code>
</pre>

下标(Subscripts)

扩展可以 向一个已有类型 添加 新下标
eg:
<pre>
<code>
`
extension String
{
enum BigOrSmall
{
case Big
case Small
}
subscript(bigOrSmall: BigOrSmall) -> String
{
switch bigOrSmall
{
case .Big:
return self.uppercaseString
case .Small:
return self.lowercaseString
}
}
}

let someStr = "abc低EFG"
print(someStr[.Big])
print(someStr[.Small])
//打印
//ABC低EFG
//abc低efg
`
</code>
</pre>

嵌套类型(Nested Types)

扩展可以向已有的类、结构体枚举添加新的嵌套类型
eg.
<pre>
<code>
`
extension Int
{
enum Kind:String
{ case Negative, Zero, Positive }

var kind: Kind
{
    switch self
    {
    case 0: return .Zero
    case let x where x > 0: return .Positive
    default:  return .Negative
    }
}

}

for number in [3, 19, -27, 0, -6, 0, 7]{ print(number.kind) }

//打印
//Positive
//Positive
//Negative
//Zero
//Negative
//Zero
//Positive
`
</code>
</pre>

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

推荐阅读更多精彩内容