你好,歡迎來到IOS教程網

 Ios教程網 >> IOS編程開發 >> IOS開發綜合 >> iOS 程序指南:在 Objective-C 中模仿多繼承

iOS 程序指南:在 Objective-C 中模仿多繼承

編輯:IOS開發綜合

首先,不得不說的是。這個技巧雖然一點也不復雜,但是對於程序員對自己代碼的理解有非常高的要求。Objective-C 不支持多繼承畢竟有它的原因。多繼承使得我們可以把許許多多不同對象的特性組合到一起,這個的結果大多會使得你的對象變的龐大,並且具有多個接口。而我們在 iPhone 開發中更經常使用而且更適應的是精細的,只為完成自己功能而設計的對象。事實上,現在所要介紹的方法也只是多繼承的一個模仿。它也傾向於鼓勵你的對象變的精巧,各司其職。而這一切都是由 Objective-C 的運行庫提供的。

 


當然,我們為什麼要使用多繼承呢?多繼承在某些特定的時候有非常顯著的好處。比如當我們設計游戲的時候(我特別喜歡用星際爭霸來做例子),我們設計了一個對象名為基地,然後有第二個對象名為母艦核心。很顯然的是,這兩個對象應該繼承不同的父類:建築與單位。但是某一天,我們的游戲設計人員認為,應該給母艦核心一個技能,讓他能把自己的攻擊能力轉移到基地身上,這樣基地就可以攻擊了。這個時候我們應該怎麼辦呢?我們可以為基地單獨寫一個攻擊方法。或者我們可以簡單的,(在多繼承的情況下)讓基地繼承於母艦核心,這樣就可以借用母艦核心的部分方法了。

 


當然,事實上只要是游戲就是和 Objective-C 不沾邊的。不過類似的場景可以有很多。Objective-C 理解這一點,然後為我們提供了一個解決方案。也就是運行時的消息轉發。


- (void) forwardInvocation:(NSInvocation *)anInvocation;

它的工作原理是這樣的。當一個對象收到一條它所未定義的消息的時候,它並不是第一時間拋出異常然後讓調用棧去捕獲,而是提供了第二次機會,它會調用 forwardInvocation: 這個方法,嘗試把這條消息交給其他對象處理。(其他你定義的,這個對象裡有 reference 的對象。)NSInvocation 這個類裡面封裝了消息名稱,以及傳遞的參數這一系列信息。這樣的話,我們就可以根據消息的性質,把這個消息移交給其他對象。其返回值也會傳回給我們,這樣,我們自己的對象的工作方式就和遠端的另一個對象顯得一致了。

 


這樣做有什麼好處呢?第一,如果你的對象已經定義了這個方法,那麼 forwardInvocation 是不會被觸發的,這點就和函數的重寫有些類似。第二,相比自己重新寫一個方法,在開發者的角度而言,你所尋求的其他對象很可能不只能夠處理這一個消息,很有可能它還會處理其他你理應當處理但是只在運行時才能發現的問題(比如在某個時間點之後對方對自己提供的對象進行了升級。)所以,利用這樣一個運行時消息轉發的機制,可以很不錯的模仿多繼承的功能,順便保留了 Objective-C 的精巧特性。

 


第三,這個方法為我們提供了一個非常優良的模式。也就是 Cocoa 框架裡面,NSObject 之外的另一大根類,NSProxy 所使用的模式。有一些時候,我們會遇到一些很龐大的對象。它可能是一個單例,可能是其他的。大多數時候我們只需要獲得它的某些描述信息(想到了什麼,流媒體還是網絡?)而不需要使用它。因為初始化這樣一個類消耗的資源太大了,所以我們希望盡量延遲這個操作:最好的情況是不要做!在這個時候,我們就可以設計一個前端的輕量級對象,它可以應對大多數接受到的消息,而當自己接受到未定義的消息的時候,再將其轉發給背後的龐大的對象:這個時候才會調用這個對象的單例,進行初始化。從使用者的角度上講,這個前端的輕量級對象的表現和預期的一模一樣。你看,這是不是很酷?

 


當然,這樣一個方法不可能沒有它的陷阱。首先,respondsToSelector 等系列方法依然會認為自己不能對這一些准備轉發的消息做出反應。第二,拋出異常的對象不再是你的對象而是遠端的那個對象。所以 Oops,最開始說什麼來著?要利用這個技巧,必須得對自己的對象以及自己准備轉發消息的目標對象有深刻的了解才行。就正如蘋果官方文檔所言:如果不是實在沒轍,千萬別用它!

 

  1. 上一頁:
  2. 下一頁:
蘋果刷機越獄教程| IOS教程問題解答| IOS技巧綜合| IOS7技巧| IOS8教程
Copyright © Ios教程網 All Rights Reserved