1.Class 和 Struct
要知道ObjC,Swift都是面向?qū)ο缶幊蹋幊虘?yīng)用中:通常先定義一個(gè)基類(base Class),緊接著為該類添加一些基礎(chǔ)屬性以及方法,這便是父類(super class);倘若現(xiàn)在要聲明一個(gè)繼承于它的子類,通常是這么聲明的class ChildClass:SuperClass{},這時(shí)候該子類就擁有了父類的所有特性(包括屬性和方法),子類還可以通過(guò)override來(lái)重寫(xiě)父類的計(jì)算屬性以及方法,但是卻無(wú)法重寫(xiě)父類的存儲(chǔ)屬性,這點(diǎn)值得引起注意。為了直觀表達(dá),簡(jiǎn)單寫(xiě)個(gè)小demo:
// 父類
class SuperClass{
// 包含一個(gè)name屬性
var storedVar:String = "storedVar"
var computedVar:String {
return "computedVar"
}
// 打印名字
func descriptionClass(){
print("storedVar is \(storedVar)")
print("computedVar is \(computedVar)")
}
}
// 子類2
class FirstChildClass:SuperClass{
// 可以什么都不寫(xiě)
}
// 子類2
class SecondChildClass:SuperClass{
// 重寫(xiě)父類屬性中的名字
override var computedVar:String{
return "修改后的computedVar"
}
override func descriptionClass(){
print("cc storedVar is \(storedVar)")
print("cc computedVar is \(computedVar)")
}
}
var fc = FirstChildClass()
var sc = SecondChildClass()
fc.descriptionClass()
sc.descriptionClass()
Class暫時(shí)告一段落,我迫不及待想要向你推銷(xiāo)Struct了!
- A:重寫(xiě)上述代碼,用結(jié)構(gòu)體??
- B:不不!結(jié)構(gòu)體是值類型,且不支持繼承。
- A:難道用協(xié)議?
- B:Bingo!
- A:倒是一個(gè)不錯(cuò)的注意,指定一個(gè)協(xié)議,然后讓兩個(gè)子類遵循這個(gè)協(xié)議即可,不過(guò)....
- B:看來(lái)你也知曉弊端了,遵循協(xié)議后,必須各自實(shí)現(xiàn)協(xié)議中的方法,由于結(jié)構(gòu)體又是值類型,那么相當(dāng)于方法與結(jié)構(gòu)體之間是一對(duì)一,而非Class中子類只要繼承父類,共同指向父類中的方法。
這段對(duì)話中協(xié)議的應(yīng)用代碼如下:
protocol ClassProtocol{
var name:String{get set}
func description()
}
struct FirstClass:ClassProtocol{
var name = "firstClass"
func description() {
print("First class")
}
}
struct SecondClass:ClassProtocol {
var name = "firstClass"
func description() {
print("Second class")
}
}
顯然這并不是我們想要的結(jié)果,和類中繼承大相徑庭。
不過(guò)Swift2.0語(yǔ)法的更新為我們帶來(lái)了協(xié)議上的改動(dòng),增加了Extension。
或許你還不理解,首先Extension譯為擴(kuò)展、拓展,顧名思義就是對(duì)已聲明的協(xié)議補(bǔ)充額外的默認(rèn)行為。這里我不得不友情提示,Extension中哪些內(nèi)容是不被允許的。
- 有童鞋聲明了一個(gè)協(xié)議,卻遺漏了某個(gè)協(xié)議方法,這時(shí)候想要通過(guò)extension來(lái)補(bǔ)充,例如
extension ClassProtocol{func extraMethod()}會(huì)提示報(bào)錯(cuò)"expected '{' in body of function declare",先前說(shuō)了擴(kuò)展中需要添加額外的默認(rèn)實(shí)現(xiàn),而非協(xié)議中只要求方法聲明即可滿足。 - 存儲(chǔ)屬性。例如
extension ClassProtocol{ var name2:String = "hello"}是不被允許的。
使用面向協(xié)議編程
不如來(lái)個(gè)角色扮演游戲來(lái)講解:游戲中,有敵人Enemy,我們規(guī)定敵人要有名字以及攻擊手段,顯然不同敵人都各有不同,但是有一點(diǎn)我們規(guī)定是一樣的:死的時(shí)候大喊一聲“我掛了”(調(diào)皮了)。為此先制定一個(gè)協(xié)議。
protocol Enemy{
var name:String{get set} //名字
func attack() //攻擊手段
}
extension Enemy{
func deadBehavior(){
print("掛了")
}
}
// 小羅羅
struct SimpleEnemy:Enemy{
var name = "小啰啰"
func attack(){
print("用刀砍")
}
}
// Boss
struct Boss:Enemy{
var name = "boss"
func attack(){
print("用槍打")
}
}
var s = SimpleEnemy()
var b = Boss()
s.deadBehavior()
b.deadBehavior() //可以看到通過(guò)協(xié)議擴(kuò)展它們擁有共同的方法了?。?!
倘若終極Boss想要特立獨(dú)行點(diǎn),死時(shí)候的喊的霸氣點(diǎn),我們還可以重寫(xiě)默認(rèn)的協(xié)議方法呢!
struct SuperBoss:Enemy{
var name = "終極boss"
func attack(){
print("無(wú)所不能")
}
func deadBehavior(){
print("我還會(huì)再回來(lái)的")
}
}
var sb = SuperBoss()
sb.deadBehavior()
可以看到重寫(xiě)了擴(kuò)展中的默認(rèn)方法,最終會(huì)調(diào)用SuperBoss()中重寫(xiě)的deadBehavior()方法。
為了讓游戲好玩,我設(shè)定了終極Boss死后時(shí)會(huì)蛻變成另外一個(gè)Emeny。
var sb = SuperBoss()
sb.deadBehavior()
var weakSb = sb as Enemy
weakSb.deadBehavior()// 輸出掛了
可以看到終極Boss變成Enemy之后不再擁有原先的“我還會(huì)再回來(lái)的”死亡行為。
10.16日更新添加內(nèi)容
這是采用面向協(xié)議實(shí)現(xiàn)的字符校驗(yàn)第三方庫(kù),可以作為學(xué)習(xí)或者項(xiàng)目使用。地址PTStringValidator Framework
總結(jié):本文難度不大,旨在為大家講解Protocol Extension的基礎(chǔ)以及實(shí)際應(yīng)用,倘若覺(jué)得不錯(cuò),請(qǐng)訂閱我以及點(diǎn)擊喜歡。
開(kāi)設(shè)了一個(gè)swift交流群:392436022 歡迎加入。