本文參考了Swift2.2與3.0的語法,在少數(shù)地方添加了自我理解與示例.
擴(kuò)展(Extensions)
擴(kuò)展就是向一個(gè)已有的類旗扑、結(jié)構(gòu)體、枚舉類型或者協(xié)議類型 添加新功能曼库。
這包括在沒有權(quán)限獲取原始源代碼的情況下擴(kuò)展類型的能力(即逆向建模)区岗。
擴(kuò)展和Objective-C中的分類(categories)類似。
(不過與 Objective-C 不同的是,Swift 的擴(kuò)展沒有名字毁枯。)
Swift中的擴(kuò)展可以:
添加計(jì)算型屬性和計(jì)算型靜態(tài)屬性
添加實(shí)例方法和類型方法
添加新的構(gòu)造器
添加下標(biāo)
添加和使用新的嵌套類型
使一個(gè)已有類型符合某個(gè)協(xié)議
在 Swift 中,你甚至可以對(duì)一個(gè)協(xié)議(Protocol)進(jìn)行擴(kuò)展,
(你可以從協(xié)議擴(kuò)展獲取更多的細(xì)節(jié)慈缔。)
注意
擴(kuò)展可以對(duì) 一個(gè)類型 添加新的功能,但是不能重寫已有的功能。
擴(kuò)展語法(Extension Syntax)
聲明一個(gè)擴(kuò)展使用關(guān)鍵字extension
<pre>
<code>
extension SomeType { // 加到SomeType的新功能寫到這里 }
</code>
</pre>
一個(gè)擴(kuò)展可以擴(kuò)展一個(gè)已有類型使其能夠適配一個(gè)或多個(gè)協(xié)議(protocol)种玛。
<pre>
<code>
//SomeType類型遵循協(xié)議SomeProtocol, AnotherProctocol //SomeType類型是協(xié)議SomeProtocol, AnotherProctocol的成員 extension SomeType: SomeProtocol, AnotherProctocol { // 協(xié)議實(shí)現(xiàn)寫到這里 }
</code>
</pre>
按照這種方式添加協(xié)議遵循者(protocol conformance)被稱為在擴(kuò)展中添加協(xié)議成員
注意:
如果你定義了一個(gè)擴(kuò)展向一個(gè)已有類型添加新功能
那么這個(gè)新功能對(duì)該類型的所有已有實(shí)例中都是可用的
即使它們是在你的這個(gè)擴(kuò)展的前面定義的藐鹤。
計(jì)算型屬性(Computed Properties)
擴(kuò)展可以向已有類型添加計(jì)算型實(shí)例屬性和計(jì)算型類型屬性瓤檐。
下面的例子向 Swift的內(nèi)建Double類型 添加了5個(gè)計(jì)算型實(shí)例屬性
<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>
注意
擴(kuò)展
可以添加新的計(jì)算屬性
不可以添加存儲(chǔ)屬性
不可以向已有屬性添加屬性觀測(cè)器(property observers)
構(gòu)造器(Initializers)
擴(kuò)展可以向已有類型 添加 新的構(gòu)造器。
擴(kuò)展
能 向類中添加新的 便利構(gòu)造器
不能 向類中添加新的 指定構(gòu)造器 或 析構(gòu)器娱节。
指定構(gòu)造器 和 析構(gòu)器 總是由 原始的類實(shí)現(xiàn) 來提供挠蛉。
注意
如果你使用擴(kuò)展向 一個(gè)值類型 添加 一個(gè)構(gòu)造器,該值類型 已經(jīng)為所有的存儲(chǔ)屬性 提供了默認(rèn)值,而且沒有定義任何定制構(gòu)造器(custom initializers)
你可以在值類型的 擴(kuò)展構(gòu)造器中 調(diào)用默認(rèn)構(gòu)造器(default initializers) 和 逐一成員構(gòu)造器(memberwise initializers)
下面的例子定義了一個(gè) 用于描述幾何矩形 的 結(jié)構(gòu)體Rect
<pre>
<code>
`
//定義了兩個(gè) 結(jié)構(gòu)體Size和Point ,它們都把0.0作為所有屬性的默認(rèn)值:
struct Size
{
var width = 0.0, height = 0.0
}
struct Point
{
var x = 0.0, y = 0.0
}
//結(jié)構(gòu)體Rect
struct Rect
{
var origin = Point()
var size = Size()
}
//在extension中提供一個(gè)使用center和size的構(gòu)造器來擴(kuò)展Rect結(jié)構(gòu)體:
extension Rect
{
init(center: Point, size: Size)
{
let originX = center.x - (size.width / 2)
let originY = center.y - (size.height / 2)
//調(diào)用逐一成員構(gòu)造器
self.init(origin: Point(x: originX, y: originY), size: size)
}
}
//因?yàn)榻Y(jié)構(gòu)體Rect提供了其所有屬性的默認(rèn)值,可以使用默認(rèn)構(gòu)造器和逐一成員構(gòu)造器。這些構(gòu)造器可以用于構(gòu)造新的Rect實(shí)例:
let defaultRect = Rect()//使用默認(rèn)構(gòu)造器
let memberwiseRect = Rect(origin: Point(x: 2.0, y: 2.0),size: Size(width: 5.0, height: 5.0))//使用逐一成員構(gòu)造器
//調(diào)用結(jié)構(gòu)體Rect中新提供的構(gòu)造器構(gòu)造Rect實(shí)例
let centerRect = Rect(center: Point(x: 4.0, y: 4.0),size: Size(width: 3.0, height: 3.0))
`
</code>
</pre>
注意
如果你使用擴(kuò)展提供了一個(gè)新的構(gòu)造器,你依舊有責(zé)任保證構(gòu)造過程能夠讓實(shí)例完全初始化肄满。
方法(Methods)
擴(kuò)展可以向已有類型 添加新的 實(shí)例方法 和 類型方法谴古。
下面的例子為 Int類型 擴(kuò)展添加 一個(gè)名為repetitions的新實(shí)例方法
<pre>
<code>
`
extension Int
{
//repetitions方法使用了一個(gè)參數(shù),類型為 () -> () ,即沒有參數(shù)沒有返回值。
//任意整數(shù)可以調(diào)用repetitions方法,實(shí)現(xiàn)多次執(zhí)行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>
下標(biāo)(Subscripts)
擴(kuò)展可以 向一個(gè)已有類型 添加 新下標(biāo)稠歉。
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)
擴(kuò)展可以向已有的類掰担、結(jié)構(gòu)體和枚舉添加新的嵌套類型
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>