2010-06-22 114 views
1

這可能是Java編碼器報告的常見Objective-C問題,但我不知道該怎麼稱呼它或如何搜索答案。比方說,我有一個類和延伸它的另一個類:覆蓋Objective-C中的繼承類型

AbstractModel

@interface AbstractModel { 
} 

ModelImpl

@interface ModelImpl : AbstractModel { 
} 

分開這些,我還有兩節課,再一個延伸另一種:

ControllerA

@interface ControllerA { 
    AbstractModel *foo; 
} 

@property (nonatomic, retain) AbstractModel *foo; 

ControllerB

@interface ControllerB : ControllerA { 
} 

我希望能夠說foo在ControllerA可以包含AbstractModel或其任何亞型。但是,如果我嘗試在其中存儲AbstractModel以外的任何內容,編譯器會給我一個警告。 (當然,我明白,類不能真正在ObjC是抽象的,但饒了我吧。)

我也想能夠在特定的子類,以「鎖定」的foo屬性。我想說的是,ControllerB中的foo例如只能包含ModelImpl4。這可能嗎?

解決這類問題的傳統Objective-C最佳實踐是什麼?以這種方式使用繼承 - 或者爲了實現這個目標 - 在Objective-C中不是一個好主意?

+0

看看UITableView如何處理委託屬性的例子。在這種情況下,它是一個協議,但它會和一個類一樣好。 – drawnonward 2010-06-22 18:35:20

回答

3

首先,我想明白了這一點:

但是,如果我嘗試存儲任何東西,編譯器會給我一個 警告 以外的AbstractModel。

這沒有意義。您應該可以毫無困難地將子類AbstractModel分配到foo。你看到什麼問題?

接下來,你所描述的不是重寫,而是超載。你試圖改變方法的返回類型,並且你不能在ObjC中做到這一點。這個問題有很好的解決方法,但是它有點取決於你真正的目標是什麼。

  • 首先,你可以在ControllerA擺脫-foo。如果ControllerA實際上是抽象的,那麼最好不要有一個。如果ControllerA是抽象的,我絕對建議你在該層去掉foo伊娃。你應該把ivars放在子類中。

  • 或者,您可以將類型化的方法添加到子類中。例如,ControllerB除了繼承-foo之外,還會有-modelBFoo方法。這些方法將是相同的;他們只會有不同的返回類型,允許在所有呼叫者中打字。

不要忽略警告。他們在那裏保護你(而在ObjC中,他們就是你必須保護你的一切)。儘可能地限制你的類型轉換。它們將編譯器錯誤(良好)移至運行時異常(錯誤)。

+0

警告也可能來自他沒有導入ModelImpl的頭文件。我只是想到了。 – huntaub 2010-06-22 18:51:00

1

是的。解決第一個問題的最簡單方法就是忽略編譯器警告。它將在運行時工作。如果你不喜歡的警告,你可以強制轉換:

foo = (AbstractModel *)thisIsAModelImpl; 

然後,以「鎖定下來」的ControllerB,您只需將這個行添加到您的.h文件中

ModelImpl *foo; 

而且,你會想覆蓋(重新定義)ControllerB中處理foo的任何方法。

編輯:爲了清楚起見,這是我的意思是覆蓋。

如果你有方法(在ControllerA

-setFoo:(AbstractModel *)newModel; 
-(AbstractModel *)foo; 

你會改變那些行(在ControllerB

-setFoo:(ModelImpl*)newModel; 
-(ModelImpl*)foo;