2009-11-27 13 views
9

有什麼方法可以在運行時發現給定類中存在哪些子類?在Obj-C中發現給定類的子類

編輯:從目前爲止的答案,我想我需要澄清一點,我正在嘗試做什麼。我知道這在Cocoa中並不常見,並且可能會帶來一些警告。

我正在使用動態創建模式編寫解析器。 (請參閱Buck和Yacktman的Cocoa Design Patterns一書,第5章。)基本上,解析器實例處理堆棧,並實例化知道如何執行特定計算的對象。

如果我可以得到MYCommand類的所有子類,例如,我可以爲用戶提供可用命令的列表。另外,在第5章的例子中,解析器有一個替換字典,因此可以使用+, - ,*和/等運算符。 (它們被映射到MYAddCommand等等)對我來說,似乎這些信息屬於MyCommand子類,而不是解析器實例,因爲它有點違背了動態創建的想法。

回答

13

,而不是試圖自動註冊的MYCommand所有子類,爲什麼兩個不拆的問題?

首先,提供註冊類的API,比如+[MYCommand registerClass:]

然後,在MYCommand中創建代碼,這意味着任何子類都會自動註冊自己。喜歡的東西:

@implementation MYCommand 
+ (void)load 
{ 
    [MYCommand registerClass:self]; 
} 
@end 
+0

這看起來確實是正確的方式。特別是因爲文檔中提到一個類的'+ load'方法在其所有超類的「+ load」方法之後被調用。 非常感謝其他人提供的答案,但他們的答案也很好。 – 2009-11-28 16:23:02

+2

MyCommand的子類不會在其超類上調用+加載。 +只在實現它的類中調用load。 – 2014-03-19 20:44:53

+0

驚訝花了這麼長時間有人糾正我!我通常同意這裏的答案,即自動註冊是一個壞主意,應該多處理一點手動。 – 2014-03-22 13:09:38

19

不直接,沒有。但是,您可以獲得運行時註冊的所有類的列表,並可以查詢這些類的直接超類。請記住,這不允許你找到繼承樹上的所有祖先,只是直接的超類。

您可以使用objc_getClassList()來獲取在運行時註冊的Class對象的列表。然後,您可以遍歷該數組並在這些對象上調用[NSObject superclass]以獲得其超類'Class對象。如果由於某些原因,您的課程不使用NSObject作爲其根類,則可以使用class_getSuperclass()

我應該提及的是,如果您覺得有必要進行這種發現,那麼您的可能會錯誤地考慮您的應用程序的設計。最有可能的是,另一種更傳統的方式來做你正在努力完成的任務,它不涉及Objective-C運行時的自省。

+7

我會說更強烈;如果你認爲你需要在生產代碼中這樣做,那麼你很可能做錯了。向下看繼承反思是非常罕見的,並且是運行時不直接支持它的原因。你想做什麼? – bbum 2009-11-27 23:14:59

+0

@bbum我已經添加了我正在嘗試執行的操作的說明。你是否仍然認爲我做得非常錯誤?我很難想出另一種方法來做到這一點,而不需要尋找子類。 – 2009-11-28 07:34:27

4

馬克和皮包打了錢。這通常不是一個好主意。

然而,我們對我們的CocoaHeads wiki代碼,這是否:http://cocoaheads.byu.edu/wiki/getting-all-subclasses

+1

另一個警告;當做這種事情時,你最終會導致類按照他們以前從未初始化的順序進行初始化。這應該不會造成問題,但有時會因系統類中的依賴關係而有所變化,這些依賴關係可能會在不同版本之間發生變化...... – bbum 2009-11-28 03:01:06

+0

鏈接代碼的說明特別指出,此方法不會調用「+ initialize」,雖然我避難還沒有嘗試過,似乎是對的。 – 2009-11-28 07:28:36

0

有一個在我運行的瀏覽器項目here包括-subclassNamesForClass代碼:方法。請參閱RuntimeReporter.[hm]文件。

+0

謝謝,這是一個有趣的工具添加到我的腰帶。儘管我會在邁克的這個特例中採用這種方法。 – 2009-11-30 08:12:57

+0

我注意到由@NSResponder發佈的鏈接已損壞。對於那些尋找循環遍歷類層次結構的方法,我寫了一個[Class Hierarchy Logger](https://github.com/sebaven/class-hierarchy-logger),它使用了類似的方法。如果您需要更多關於如何迭代子類層次結構的信息,它可能會很有用。我希望它有幫助! – 2014-10-23 03:35:26

3

另一種方法剛剛由Matt Gallagher發佈在his blog上。