之前學習swift時的個人筆記,根據github: "the swift programming language in chinese" 學習、總結,將重要的內容提取,加以理解後整理為學習筆記,方便以後查詢用。詳細可以參考 "the swift programming language in ch ...
之前學習swift時的個人筆記,根據github:the-swift-programming-language-in-chinese學習、總結,將重要的內容提取,加以理解後整理為學習筆記,方便以後查詢用。詳細可以參考the-swift-programming-language-in-chinese,或者蘋果官方英文版文檔
當前版本是swift2.2
擴展(Extensions)
擴展 就是為一個已有的類、結構體、枚舉類型或者協議類型添加新功能。這包括在沒有許可權獲取原始源代碼的情況下擴展類型的能力(即 逆向建模 )。擴展和 Objective-C 中的分類類似。(與 Objective-C 不同的是,Swift 的擴展沒有名字。)
如果你通過擴展為一個已有類型添加新功能,那麼新功能對該類型的所有已有實例都是可用的,即使它們是在這個擴展定義之前創建的。
計算型屬性(Computed Properties)
擴展可以為已有類型添加計算型實例屬性和計算型類型屬性。不可以添加存儲性屬性
構造器(Initializers)
擴展可以為已有類型添加新的構造器。這可以讓你擴展其它類型,將你自己的定製類型作為其構造器參數,或者提供該類型的原始實現中未提供的額外初始化選項。
擴展能為類添加新的便利構造器,但是它們不能為類添加新的指定構造器或析構器。指定構造器和析構器必須總是由原始的類實現來提供。
方法(Methods)
擴展可以為已有類型添加新的實例方法和類型方法。
可變實例方法(Mutating Instance Methods)
通過擴展添加的實例方法也可以修改該實例本身。結構體和枚舉類型中修改 self 或其屬性的方法必須將該實例方法標註為 mutating,正如來自原始實現的可變方法一樣。
下麵的例子為 Swift 的 Int 類型添加了一個名為 square 的可變方法,用於計算原始值的平方值:
extension Int {
mutating func square() {
self = self * self
}
}
下標(Subscripts)
擴展可以為已有類型添加新下標。這個例子為 Swift 內建類型 Int 添加了一個整型下標。該下標 [n] 返回十進位數字從右向左數的第 n 個數字:
123456789[0] 返回 9
123456789[1] 返回 8
嵌套類型(Nested Types)
擴展可以為已有的類、結構體和枚舉添加新的嵌套類型:
協議
Mutating 方法要求
如果你在協議中定義了一個實例方法,該方法會改變採納該協議的類型的實例,那麼在定義協議時需要在方法前加 mutating 關鍵字。這使得結構體和枚舉能夠採納此協議並滿足此方法要求。
將 mutating 關鍵字作為方法的首碼,寫在 func 關鍵字之前,表示可以在該方法中修改它所屬的實例以及實例的任意屬性的值
實現協議中的 mutating 方法時,若是類類型,則不用寫 mutating 關鍵字。而對於結構體和枚舉,則必須寫 mutating 關鍵字。
協議構造器要求
協議可以要求採納協議的類型實現指定的構造器。你可以像編寫普通構造器那樣,在協議的定義里寫下構造器的聲明,但不需要寫花括弧和構造器的實體:
protocol SomeProtocol {
init(someParameter: Int)
}
構造器要求在類中的實現
你可以在採納協議的類中實現構造器,無論是作為指定構造器,還是作為便利構造器。無論哪種情況,你都必須為構造器實現標上 required 修飾符:
class SomeClass: SomeProtocol {
required init(someParameter: Int) {
// 這裡是構造器的實現部分
}
}
使用 required 修飾符可以確保所有子類也必須提供此構造器實現,從而也能符合協議。
構造器要求
協議可以要求採納協議的類型實現指定的構造器。你可以像編寫普通構造器那樣,在協議的定義里寫下構造器的聲明,但不需要寫花括弧和構造器的實體:
protocol SomeProtocol {
init(someParameter: Int)
}
構造器要求在類中的實現
你可以在採納協議的類中實現構造器,無論是作為指定構造器,還是作為便利構造器。無論哪種情況,你都必須為構造器實現標上 required 修飾符:
class SomeClass: SomeProtocol {
required init(someParameter: Int) {
// 這裡是構造器的實現部分
}
}
使用 required 修飾符可以確保所有子類也必須提供此構造器實現,從而也能符合協議。
如果一個子類重寫了父類的指定構造器,並且該構造器滿足了某個協議的要求,那麼該構造器的實現需要同時標註 required 和 override 修飾符:
protocol SomeProtocol {
init()
}
class SomeSuperClass {
init() {
// 這裡是構造器的實現部分
}
}
class SomeSubClass: SomeSuperClass, SomeProtocol {
// 因為採納協議,需要加上 required
// 因為繼承自父類,需要加上 override
required override init() {
// 這裡是構造器的實現部分
}
}
如果類已經被標記為 final,那麼不需要在協議構造器的實現中使用 required 修飾符,因為 final 類不能有子類
協議作為類型
儘管協議本身並未實現任何功能,但是協議可以被當做一個成熟的類型來使用。
- 作為函數、方法或構造器中的參數類型或返回值類型
- 作為常量、變數或屬性的類型
- 作為數組、字典或其他容器中的元素類型
通過擴展採納協議
當一個類型已經符合了某個協議中的所有要求,卻還沒有聲明採納該協議時,可以通過空擴展體的擴展來採納該協議:
struct Hamster {
var name: String
var textualDescription: String {
return "A hamster named \(name)"
}
}
extension Hamster: TextRepresentable {}
從現在起,Hamster 的實例可以作為 TextRepresentable 類型使用:
let simonTheHamster = Hamster(name: "Simon")
let v1: TextRepresentable = simonTheHamster // 可以賦值
print(v1.textualDescription)
即使滿足了協議的所有要求,類型也不會自動採納協議,必須顯式地採納協議。
協議類型的集合
協議類型可以在數組或者字典這樣的集合中使用,在協議類型提到了這樣的用法。下麵的例子創建了一個元素類型為 TextRepresentable 的數組:
let things: [TextRepresentable] = [game, d12, simonTheHamster]
如下所示,可以遍歷 things 數組,並列印每個元素的文本表示:
for thing in things {
print(thing.textualDescription)
}
// A game of Snakes and Ladders with 25 squares
// A 12-sided dice
// A hamster named Simon
thing 是 TextRepresentable 類型而不是 Dice,DiceGame,Hamster 等類型,即使實例在幕後確實是這些類型中的一種。由於 thing 是 TextRepresentable 類型,任何 TextRepresentable 的實例都有一個 textualDescription 屬性,所以在每次迴圈中可以安全地訪問 thing.textualDescription。
協議的繼承
協議能夠繼承一個或多個其他協議,可以在繼承的協議的基礎上增加新的要求。協議的繼承語法與類的繼承相似,多個被繼承的協議間用逗號分隔:
protocol InheritingProtocol: SomeProtocol, AnotherProtocol {
// 這裡是協議的定義部分
}
類類型專屬協議
你可以在協議的繼承列表中,通過添加 class 關鍵字來限制協議只能被類類型採納,而結構體或枚舉不能採納該協議。class 關鍵字必須第一個出現在協議的繼承列表中,在其他繼承的協議之前:
protocol SomeClassOnlyProtocol: class, SomeInheritedProtocol {
// 這裡是類類型專屬協議的定義部分
}
在以上例子中,協議 SomeClassOnlyProtocol 只能被類類型採納。如果嘗試讓結構體或枚舉類型採納該協議,則會導致編譯錯誤。
協議合成
有時候需要同時採納多個協議,你可以將多個協議採用 protocol
下麵的例子中,將 Named 和 Aged 兩個協議按照上述語法組合成一個協議,作為函數參數的類型:
protocol Named {
var name: String { get }
}
protocol Aged {
var age: Int { get }
}
struct Person: Named, Aged {
var name: String
var age: Int
}
func wishHappyBirthday(celebrator: protocol<Named, Aged>) {
print("Happy birthday \(celebrator.name) - you're \(celebrator.age)!")
}
協議合成並不會生成新的、永久的協議類型,而是將多個協議中的要求合成到一個只在局部作用域有效的臨時協議中。
可選的協議要求
協議可以定義可選要求,採納協議的類型可以選擇是否實現這些要求。在協議中使用 optional 關鍵字作為首碼來定義可選要求。使用可選要求時(例如,可選的方法或者屬性),它們的類型會自動變成可選的。比如,一個類型為 (Int) -> String 的方法會變成 ((Int) -> String)?。需要註意的是整個函數類型是可選的,而不是函數的返回值。