我們這次一起來回顧一下之前幾節課裡提到的繼承,我們曾在初見OPEN 裡用了一個開發手機(系統)的栗子來描述繼承這個東西,相信大家還有印象。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
class CellPhone { func call() { print("Call someone!") } func powerUp () { print("Welcome!") } func powerDown() { print("Goodbye~") } func sendMessage() { print("sent a Message!") } } |
繼承
那麼這節課我們就深入的來了解了解繼承這個概念。
這個其實也不難理解,你看,當你的父輩去世,那他們的財富就會由你繼承——好吧,這不是一件很值得開心的事情,但這畢竟是事實。
還有,比如說某一家子人父親退休了,他的公司就由兒子掌管,我們說這是“子承父業”。
最後說回到 Swift 裡邊,就是子類繼承了父類的成員。這裡我們講“成員”,就是指類裡邊的屬性和方法。
舉個栗子吧:這還是一個手機的類
1 2 3 4 5 6 7 8 9 10 11 12 |
class CellPhone { var number = 0 var battery = 100 func call() { } func message() { } } |
我們寫子類來繼承父類:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
class Phone:CellPhone { } class SmartPhone:CellPhone { func eMail() { } func internet() { } } |
對於父類 CellPhone 來說,它比較抽象,怎麼個抽像法呢?任何一部能稱得上手機的設備,肯定都具有這樣的功能——撥號,打電話,發短信。
對於子類我們確實生產的手機,它就只有最基本的功能,所以 phone 類只需要繼承自 CellPhone 就好了,它雖然沒有寫任何的屬性和方法,但它天生就有了 CellPhone 裡的全部屬性和方法。
對於我們的智能手機 smartPhone ,我們增加了發郵件和上網的功能,但沒有實現手機的基本功能——可是它繼承自 CellPhone,所以它天生就也帶有了手機的所有功能。
至於電量和號碼這兩個屬性,兩個子類則可以設定它們各自的內容。
設計一個繼承樹
假設說我們要開發遊戲,這個遊戲既有武俠也有科技,既有英雄也有美人——所以說肯定是有戰爭的——有美人嘛。有了戰爭,就要有兵器,那麼我們就創建一個關於武器的繼承樹。
首先,設計師告訴我們,一共要有以下幾種武器:機槍、手槍、步槍、長劍、開山刀、木棍、內力(這個也算?)、鐵鎚、弩箭、弓箭、暗器……好了,夠多了。
第一步,找出具有共同屬性和行為的對象
問一問自己:這些武器都有什麼共同點?
啊……這太麻煩了,為什麼不干脆每一個武器來一個類呢?
——也不是不行,但是這樣的話肯定就會有好多重複的代碼了,這樣會讓整個代碼行數大大增加,一個是不利於維護,一旦我們要修改這些武器的某些屬性呢?挨個改吧!另一個,就是你程序的 bug 數量是和代碼行數成正比的……所以我們有必要有責任也有義務保證代碼的簡潔。
好了,這些武器肯定得有個屬性來保存它們的模型,還得有耐久度吧?得有攻擊力,有攻擊範圍,還得有攻擊類型,有等級要求……暫時這麼多吧
它們的行為,比如說有攻擊,防禦,警戒……這樣,我們就有了三個方法:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
class 武器 { var 模型 = "" var 耐久度 = 0.0 var 攻击力 = 0.0 var 等级需求 = 0 var 攻击类型 = 0 func 攻击() {} func 防御 () {} func 警戒() {} } |
這樣,我們就能從武器這裡繼承出各種各樣的武器了!來我們算一算,假設設計師要100中特定的武器,難道真的要把上邊這樣的代碼重複寫一百遍嗎? ! (小學生都不屑如此啦)
好了,現在我們再來看看,冷兵器和熱兵器是不同的,它們的攻擊方法完全不一樣,刀和劍都可以揮砍,但弩和弓就要射擊,我們讓子類自行覆蓋父類的方法——覆蓋後邊再說,簡單的用法你是知道的。
但是還有個問題,手槍機槍都要有子彈有彈夾,這些似乎還是可以提取出來——沒錯,在眾多子類裡邊,尋找更多可以抽象化的方法是個不錯的選擇,我們來設計另外一個武器的子類但又是槍支的父類:
1 2 3 4 5 6 7 |
class 枪械:武器 { var 弹药 = 0 var 弹夹 = 0 override func 攻击() { } override func 防御() { } } |
這樣,我們用槍械這個類去繼承出一個子類的話,那它就有了彈藥和彈夾,還有屬於槍械的攻擊防禦方法。
完成類的繼承樹
按照上邊的設計思路,我們現在來完成這個繼承樹:
等等,到底調用哪個方法?
現在我們有了繼承樹,也按照繼承樹繼承出了最終的實例……可是這個時候怎麼確定調用的方法在哪裡呢?
首先,既然我們有了繼承樹,那麼編譯器肯定也能夠知道,那就是說肯定會找到你要調用的方法。
其次,一般我們按照一個遞歸的方式來查詢,從這個繼承樹最底下開始(也就是最具體的對像開始),一層一層往上查找,知道找到一個對應的——也就是說最接近對象的那個方法就是我們要調用的方法。
比如我們創建了一個手槍的實例,手槍裡並沒有攻擊的方法,我們調用攻擊,編譯器就會網上查找,找到了父類裡重寫了的攻擊方法——而不是找到最頂層的最原始的攻擊方法。
轉載請保留出處和原文鏈接:https://www.logcg.com/archives/1118.html
註釋