本文參考了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>