之前學(xué)習(xí)swift時(shí)的個(gè)人筆記恢总,根據(jù)github:the-swift-programming-language-in-chinese學(xué)習(xí)迎罗、總結(jié),將重要的內(nèi)容提取片仿,加以理解后整理為學(xué)習(xí)筆記纹安,方便以后查詢用。詳細(xì)可以參考the-swift-programming-language-in-chinese砂豌,或者蘋果官方英文版文檔
當(dāng)前版本是swift2.2
擴(kuò)展(Extensions)
擴(kuò)展 就是為一個(gè)已有的類厢岂、結(jié)構(gòu)體、枚舉類型或者協(xié)議類型添加新功能阳距。這包括在沒(méi)有權(quán)限獲取原始源代碼的情況下擴(kuò)展類型的能力(即 逆向建模 )塔粒。擴(kuò)展和 Objective-C 中的分類類似。(與 Objective-C 不同的是筐摘,Swift 的擴(kuò)展沒(méi)有名字卒茬。)
如果你通過(guò)擴(kuò)展為一個(gè)已有類型添加新功能,那么新功能對(duì)該類型的所有已有實(shí)例都是可用的咖熟,即使它們是在這個(gè)擴(kuò)展定義之前創(chuàng)建的圃酵。
計(jì)算型屬性(Computed Properties)
擴(kuò)展可以為已有類型添加計(jì)算型實(shí)例屬性和計(jì)算型類型屬性。不可以添加存儲(chǔ)性屬性
構(gòu)造器(Initializers)
擴(kuò)展可以為已有類型添加新的構(gòu)造器馍管。這可以讓你擴(kuò)展其它類型郭赐,將你自己的定制類型作為其構(gòu)造器參數(shù),或者提供該類型的原始實(shí)現(xiàn)中未提供的額外初始化選項(xiàng)确沸。
擴(kuò)展能為類添加新的便利構(gòu)造器捌锭,但是它們不能為類添加新的指定構(gòu)造器或析構(gòu)器躬存。指定構(gòu)造器和析構(gòu)器必須總是由原始的類實(shí)現(xiàn)來(lái)提供。
方法(Methods)
擴(kuò)展可以為已有類型添加新的實(shí)例方法和類型方法舀锨。
可變實(shí)例方法(Mutating Instance Methods)
通過(guò)擴(kuò)展添加的實(shí)例方法也可以修改該實(shí)例本身岭洲。結(jié)構(gòu)體和枚舉類型中修改 self 或其屬性的方法必須將該實(shí)例方法標(biāo)注為 mutating,正如來(lái)自原始實(shí)現(xiàn)的可變方法一樣坎匿。
下面的例子為 Swift 的 Int 類型添加了一個(gè)名為 square 的可變方法盾剩,用于計(jì)算原始值的平方值:
extension Int {
mutating func square() {
self = self * self
}
}
下標(biāo)(Subscripts)
擴(kuò)展可以為已有類型添加新下標(biāo)。這個(gè)例子為 Swift 內(nèi)建類型 Int 添加了一個(gè)整型下標(biāo)替蔬。該下標(biāo) [n] 返回十進(jìn)制數(shù)字從右向左數(shù)的第 n 個(gè)數(shù)字:
123456789[0] 返回 9
123456789[1] 返回 8
嵌套類型(Nested Types)
擴(kuò)展可以為已有的類告私、結(jié)構(gòu)體和枚舉添加新的嵌套類型:
協(xié)議
Mutating 方法要求
如果你在協(xié)議中定義了一個(gè)實(shí)例方法,該方法會(huì)改變采納該協(xié)議的類型的實(shí)例承桥,那么在定義協(xié)議時(shí)需要在方法前加 mutating 關(guān)鍵字驻粟。這使得結(jié)構(gòu)體和枚舉能夠采納此協(xié)議并滿足此方法要求。
將 mutating 關(guān)鍵字作為方法的前綴凶异,寫在 func 關(guān)鍵字之前蜀撑,表示可以在該方法中修改它所屬的實(shí)例以及實(shí)例的任意屬性的值
實(shí)現(xiàn)協(xié)議中的 mutating 方法時(shí),若是類類型剩彬,則不用寫 mutating 關(guān)鍵字酷麦。而對(duì)于結(jié)構(gòu)體和枚舉,則必須寫 mutating 關(guān)鍵字喉恋。
協(xié)議構(gòu)造器要求
協(xié)議可以要求采納協(xié)議的類型實(shí)現(xiàn)指定的構(gòu)造器沃饶。你可以像編寫普通構(gòu)造器那樣,在協(xié)議的定義里寫下構(gòu)造器的聲明轻黑,但不需要寫花括號(hào)和構(gòu)造器的實(shí)體:
protocol SomeProtocol {
init(someParameter: Int)
}
構(gòu)造器要求在類中的實(shí)現(xiàn)
你可以在采納協(xié)議的類中實(shí)現(xiàn)構(gòu)造器糊肤,無(wú)論是作為指定構(gòu)造器,還是作為便利構(gòu)造器氓鄙。無(wú)論哪種情況馆揉,你都必須為構(gòu)造器實(shí)現(xiàn)標(biāo)上 required 修飾符:
class SomeClass: SomeProtocol {
required init(someParameter: Int) {
// 這里是構(gòu)造器的實(shí)現(xiàn)部分
}
}
使用 required 修飾符可以確保所有子類也必須提供此構(gòu)造器實(shí)現(xiàn),從而也能符合協(xié)議玖详。
構(gòu)造器要求
協(xié)議可以要求采納協(xié)議的類型實(shí)現(xiàn)指定的構(gòu)造器把介。你可以像編寫普通構(gòu)造器那樣勤讽,在協(xié)議的定義里寫下構(gòu)造器的聲明蟋座,但不需要寫花括號(hào)和構(gòu)造器的實(shí)體:
protocol SomeProtocol {
init(someParameter: Int)
}
構(gòu)造器要求在類中的實(shí)現(xiàn)
你可以在采納協(xié)議的類中實(shí)現(xiàn)構(gòu)造器,無(wú)論是作為指定構(gòu)造器脚牍,還是作為便利構(gòu)造器向臀。無(wú)論哪種情況,你都必須為構(gòu)造器實(shí)現(xiàn)標(biāo)上 required 修飾符:
class SomeClass: SomeProtocol {
required init(someParameter: Int) {
// 這里是構(gòu)造器的實(shí)現(xiàn)部分
}
}
使用 required 修飾符可以確保所有子類也必須提供此構(gòu)造器實(shí)現(xiàn)诸狭,從而也能符合協(xié)議券膀。
如果一個(gè)子類重寫了父類的指定構(gòu)造器君纫,并且該構(gòu)造器滿足了某個(gè)協(xié)議的要求,那么該構(gòu)造器的實(shí)現(xiàn)需要同時(shí)標(biāo)注 required 和 override 修飾符:
protocol SomeProtocol {
init()
}
class SomeSuperClass {
init() {
// 這里是構(gòu)造器的實(shí)現(xiàn)部分
}
}
class SomeSubClass: SomeSuperClass, SomeProtocol {
// 因?yàn)椴杉{協(xié)議芹彬,需要加上 required
// 因?yàn)槔^承自父類蓄髓,需要加上 override
required override init() {
// 這里是構(gòu)造器的實(shí)現(xiàn)部分
}
}
如果類已經(jīng)被標(biāo)記為 final,那么不需要在協(xié)議構(gòu)造器的實(shí)現(xiàn)中使用 required 修飾符舒帮,因?yàn)?final 類不能有子類
協(xié)議作為類型
盡管協(xié)議本身并未實(shí)現(xiàn)任何功能会喝,但是協(xié)議可以被當(dāng)做一個(gè)成熟的類型來(lái)使用。
- 作為函數(shù)玩郊、方法或構(gòu)造器中的參數(shù)類型或返回值類型
- 作為常量肢执、變量或?qū)傩缘念愋?/li>
- 作為數(shù)組、字典或其他容器中的元素類型
通過(guò)擴(kuò)展采納協(xié)議
當(dāng)一個(gè)類型已經(jīng)符合了某個(gè)協(xié)議中的所有要求译红,卻還沒(méi)有聲明采納該協(xié)議時(shí)预茄,可以通過(guò)空擴(kuò)展體的擴(kuò)展來(lái)采納該協(xié)議:
struct Hamster {
var name: String
var textualDescription: String {
return "A hamster named \(name)"
}
}
extension Hamster: TextRepresentable {}
從現(xiàn)在起,Hamster 的實(shí)例可以作為 TextRepresentable 類型使用:
let simonTheHamster = Hamster(name: "Simon")
let v1: TextRepresentable = simonTheHamster // 可以賦值
print(v1.textualDescription)
即使?jié)M足了協(xié)議的所有要求侦厚,類型也不會(huì)自動(dòng)采納協(xié)議耻陕,必須顯式地采納協(xié)議。
協(xié)議類型的集合
協(xié)議類型可以在數(shù)組或者字典這樣的集合中使用刨沦,在協(xié)議類型提到了這樣的用法淮蜈。下面的例子創(chuàng)建了一個(gè)元素類型為 TextRepresentable 的數(shù)組:
let things: [TextRepresentable] = [game, d12, simonTheHamster]
如下所示,可以遍歷 things 數(shù)組已卷,并打印每個(gè)元素的文本表示:
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 等類型侧蘸,即使實(shí)例在幕后確實(shí)是這些類型中的一種裁眯。由于 thing 是 TextRepresentable 類型,任何 TextRepresentable 的實(shí)例都有一個(gè) textualDescription 屬性讳癌,所以在每次循環(huán)中可以安全地訪問(wèn) thing.textualDescription穿稳。
協(xié)議的繼承
協(xié)議能夠繼承一個(gè)或多個(gè)其他協(xié)議,可以在繼承的協(xié)議的基礎(chǔ)上增加新的要求晌坤。協(xié)議的繼承語(yǔ)法與類的繼承相似逢艘,多個(gè)被繼承的協(xié)議間用逗號(hào)分隔:
protocol InheritingProtocol: SomeProtocol, AnotherProtocol {
// 這里是協(xié)議的定義部分
}
類類型專屬協(xié)議
你可以在協(xié)議的繼承列表中,通過(guò)添加 class 關(guān)鍵字來(lái)限制協(xié)議只能被類類型采納骤菠,而結(jié)構(gòu)體或枚舉不能采納該協(xié)議它改。class 關(guān)鍵字必須第一個(gè)出現(xiàn)在協(xié)議的繼承列表中,在其他繼承的協(xié)議之前:
protocol SomeClassOnlyProtocol: class, SomeInheritedProtocol {
// 這里是類類型專屬協(xié)議的定義部分
}
在以上例子中商乎,協(xié)議 SomeClassOnlyProtocol 只能被類類型采納央拖。如果嘗試讓結(jié)構(gòu)體或枚舉類型采納該協(xié)議,則會(huì)導(dǎo)致編譯錯(cuò)誤。
協(xié)議合成
有時(shí)候需要同時(shí)采納多個(gè)協(xié)議鲜戒,你可以將多個(gè)協(xié)議采用 protocol<SomeProtocol, AnotherProtocol> 這樣的格式進(jìn)行組合专控,稱為 協(xié)議合成(protocol composition)。你可以在 <> 中羅列任意多個(gè)你想要采納的協(xié)議遏餐,以逗號(hào)分隔伦腐。
下面的例子中,將 Named 和 Aged 兩個(gè)協(xié)議按照上述語(yǔ)法組合成一個(gè)協(xié)議失都,作為函數(shù)參數(shù)的類型:
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)!")
}
協(xié)議合成并不會(huì)生成新的蔗牡、永久的協(xié)議類型,而是將多個(gè)協(xié)議中的要求合成到一個(gè)只在局部作用域有效的臨時(shí)協(xié)議中嗅剖。
可選的協(xié)議要求
協(xié)議可以定義可選要求辩越,采納協(xié)議的類型可以選擇是否實(shí)現(xiàn)這些要求。在協(xié)議中使用 optional 關(guān)鍵字作為前綴來(lái)定義可選要求信粮。使用可選要求時(shí)(例如黔攒,可選的方法或者屬性),它們的類型會(huì)自動(dòng)變成可選的强缘。比如督惰,一個(gè)類型為 (Int) -> String 的方法會(huì)變成 ((Int) -> String)?。需要注意的是整個(gè)函數(shù)類型是可選的旅掂,而不是函數(shù)的返回值赏胚。