2011-02-26 52 views
1

我正在創建一個Cocoa庫,用於連接到我公司生產的嵌入式設備。我有一個超類,我們稱之爲Device,以及一些子類,爲不同的設備型號,我們稱之爲Device1Device2創建後更改實例化對象的子類

我需要支持的設備型號的自動檢測,這可以在連接並登錄到設備後確定。由於登錄代碼對所有設備都是通用的,因此可以在超類中處理。登錄後,設備將需要由其模型的適當子類表示。

我設想實例化Device超類的一個對象,登錄到設備以讀取模型,然後用相應子類的實例替換對象,如Device1。我知道有可能在-init方法中返回一個不同的對象,但我的問題是設備的通信可能很長,所以應該可以使用回調/代理來實現。

是否可以在-init方法之後更改實例化對象的子類?還是有更簡單/更好的方法來實現我想要做的事情?

回答

1

一種方法是使用的NSProxy定製子類的實例,而不是你的Device超來處理初始登錄和設備檢測。一旦設備類型已知,您可以設計NSProxy將其自己變成適當的Device子類的實例。

NSProxy利用了Objective-C運行時系統的一個特性,它允許它的實例注意他們何時收到了用於實際目標實例的消息。代理然後可以將消息轉發給其目標,或者將其自身轉換爲目標類型的實例並將消息轉發給自己。 (聲音,奇怪的,我知道,但在實踐中非常酷)

這裏的類描述的第一段:

NSProxy是一個定義的API充當 作爲獨立對象的抽象超 -ins for other objects or for objects that does not exist。 通常,向代理髮送的消息是 轉發給真實對象或導致 代理加載(或將自身轉換爲 )爲真實對象。 的子類NSProxy可用於實現 透明分佈式消息傳遞(例如,對於 示例,NSDistantObject)或用於創建昂貴的對象的實例化 。

NSProxy實現可以包括由Device類層次結構來實現所需的連接,登錄等方法,但不方法。代理實例可以在檢測到設備類型時選擇目標類。只要您發送由Device執行的消息,它就會自動將其自身變爲該類的一個實例,但不會由代理實現。

+0

所以我會讓我的父'Device'類從'NSProxy'而不是'NSObject'繼承?您是否能夠以這種方式提供使用'NSProxy'的基本代碼示例? –

+0

不,您的'NSProxy'的子類會創建基本上*假裝它們是'Device'子類的實例的實例。 Mike Ash在這裏有一篇出色的文章和示例代碼解決方案:http://www.mikeash.com/pyblog/friday-qa-2010-02-26-futures.html – jlehr

+0

我對「NSProxy」進行了更深入的研究它看起來會適合我。謝謝你的幫助。現在我知道要尋找什麼。 –

0

我建議你創建一個factory來實例化你的具體的Device子類,這將刪除像做一個對象的類這樣的骯髒的技巧的噓聲,可能是一個更乾淨的解決方案,這裏是一個粗略的例子,像:

@implementation DeviceFactory 

+ (Device *) detectAndMakeDevice 
{ 
    // Do your detection code here, this assumes that Device1 and Device2 are 
    // both subclasses of Device. 

    Device * dev; 

    if(deviceConnected == kDevice1) 
    dev = [[Device1 alloc] init]; 

    else if(deviceConnected == kDevice2) 
    dev = [[Device2 alloc] init]; 

    else 
    dev = nil; 

    return dev; 
} 

@end 
+0

我原本是這樣想的。但是,檢測代碼可能需要長達一分鐘的時間(對於慢速通信),這是需要很長時間才能阻止的。阻止意味着用戶界面無法獲得反饋,用戶無法取消。 –

+0

啊,我誤解了你的問題。如果等待設備出現問題,如果您在另一個線程中初始化設備,可能會有所幫助。看看[NSOperation](http://developer.apple.com/cocoa/managingconcurrency.html),它很好地抽象了多線程。然後你可以在你的Device類中擁有一個像'BOOL isInitialized'這樣的屬性並且發送消息' - (void)initializationFinishedForDevice:(Device *)'到一個DeviceDelegate對象來通知你的其他組件。 [關於如何使用委託的更多信息](http://stackoverflow.com/questions/626898/#626946) – Torsten

+0

當初始化完成後,如何將對象從'Device'更改爲'Device1'? –