2013-03-07 48 views
3

我有兩個類,1類和類2,第二個從第一個繼承了父母的隱藏方法。我需要重寫Class1的-update方法來實現我的目標。繼承方法中的-update方法的變化是在代碼中間執行的,所以我不能使用[超級更新]。這就是爲什麼我需要將原始方法從父級複製粘貼到繼承類。此方法使用父級的私有方法,因此當我嘗試重寫時,由於Class2僅導入Class1.h,因此我收到了私有方法缺失的警告。爲了澄清,這裏是代碼:如何讓繼承類能夠看到在Objective-C

Class1.h:

@interface Class1 : NSObject 
-(void) update; 
@end 

Class1.m:

@interface Class1 (Private) 
-(void) private1; 
-(void) private2; 
@end 

@implementation Class1 

-(void) update 
{ 
    [self private1]; 
    [self private2]; 
} 

-(void) private1 
{ 
    // some code 
} 

-(void) private2 
{ 
    // another code 
} 

@end 

Class2.h:

@interface Class2 : Class1 
-(void) update; 
@end 

Class2.m:

@implementation Class2 

-(void) update 
{ 
    [self private1]; // warning here 
    // do my own stuff between private methods, that is the reason of inheritance 
    [self private2]; // warning too 
} 

@end 

另外,Class1不在我的所有權,它是一個來自開源庫(準確地說Cocos3D),所以我不能改變它(這就是爲什麼我繼承)。

的問題是:我怎麼能刪除警告?我能看到的唯一解決方案是將私有方法的簽名複製到Class2,但它似乎是一個骯髒的伎倆。或者,如果有人沒有指出如何去除警告,那將是完美的,但如何更好地改變方法來實現我的目標。

+0

複製類擴展'@interface Class1的(私人)... @ end'似乎是一個乾淨的解決方案給我。使用'performSelector'或'objc_msgSend'將是一個骯髒的伎倆。 – 2013-03-07 13:54:53

+1

如何將這些常用方法應用到公共可視化中,如何在子類中使用。 – 2013-03-07 13:58:04

+0

@MartinR好吧,-performSelector是最有趣的解決方案,但是由於我從原始的更新中複製粘貼代碼,重寫調用私有方法似乎太不舒服(實際上大約有10種這樣的方法) – medvedNick 2013-03-07 14:00:37

回答

7

無需交叉混合,performSelector:或任何其他運行時雞姦。

只是移動或複製此:

@interface Class1 (Private) 
-(void) private1; 
-(void) private2; 
@end 

要你的子類的.m文件的開頭。

正常情況下,當試圖爲方法實現類似@protected的作用域時,聲明類似於Class1_Private.h之類的頭文件,並且頭文件將設置爲Xcode中的private角色。

正如其他人已經指出的,通過這種機制暴露私人方法有點危險。鑑於Cocos2D是開源的,這種危險有所緩解,或者你總是可以直接修改它。當然,這樣做意味着你實際上有一個分支,維護成本很高。

如果這是其他開發人員可能做的事情,我會建議通過Cocos2D提交一個錯誤,要求將這些方法暴露給子類。

-2

你應該能夠使用categories來解決這個問題,以擴展你的原始類,並嘗試method swizzling來實現你想要的行爲。

+0

,因爲原始類別的類別無法訪問.m文件中的專用類別,所以無法正常工作。所以這與我目前使用繼承類的代碼幾乎一樣。 – medvedNick 2013-03-07 14:19:03

+0

@medvedNick我的不好,我沒有考慮。我想你需要複製並粘貼,然後使用'performSelector'。因爲在任何情況下,這種情況在設計上都有點不好,這可能是保持東西清潔的最佳解決方案。 – beegz 2013-03-07 14:59:22

2

的方式做蘋果這是使可以在子類公共覆蓋的任何方法,但記錄的事實,他們不應該被直接調用,並且只在那裏被覆蓋。 Apple的代碼文檔(通常)是全面的,並經常提到,所以這是有效的。當然,典型的第三方代碼沒有很好的文檔記錄,也沒有文檔可能被讀取......

另一種解決方案:我經常創建第二個名爲「MyClass + SubclassMethods.h」的頭,並公開聲明子類可覆蓋,但在其他類別中是私有方法。在基類和子類的用戶的源文件中,這不會被導入,所以這些方法保持(有效)私有。在基類的子類中,我導入「MyClass + SubclassMethods.h」以允許我重寫/調用這些方法。這不是一個完美的解決方案,但沒有Objective-C中'受保護'方法的概念,我不確定有更好的方法。

+0

任何人都知道蘋果文檔不應直接調用的示例嗎? – malhal 2017-01-25 15:23:00

0

由於無法修改Class1,所以在另一個響應中建議的類別是一個很好的解決方案。如果可能對源做出調整,則在單獨的頭文件中聲明的類擴展和在Class1實現和Class2實現文件中都會#imported將是方式,因爲那樣您不僅可以共享私有方法,還可以共享這種方式標記爲@public或@protected的實例變量。瞭解更多關於類擴展從這裏:

http://developer.apple.com/library/ios/#documentation/cocoa/conceptual/ProgrammingWithObjectiveC/CustomizingExistingClasses/CustomizingExistingClasses.html

簡單地說,一個類擴展有點像一個類別(有時稱爲私人類別),但它只能在同一個編譯單元被宣佈爲所在班級它的擴展是實現的,它可以聲明(和自動合成)屬性和實例變量。有包括Xcode中創建類擴展源代碼模板(見下文)。

Class extension creation in Xcode

+0

這會工作,但不是在我的情況。正確地閱讀我的問題 - 我無法修改Class1 – medvedNick 2013-03-08 00:08:55

+0

糟糕,沒錯,沒有看到大膽的位:-)我會調整答案來說明這一點。 – mz2 2013-03-08 09:02:56

+0

我的答案已經加粗了。我的錯,我之前沒有這樣做過 – medvedNick 2013-03-08 18:00:48