2010-06-10 44 views
0

好的,所以我使用Objective-C。現在,假設我有:Obj-c方法重載/多態問題

TopClass : NSObject 
- (int) getVal {return 1;} 
MidClass : TopClass 
- (int) getVal {return 2;} 
BotClass : MidClass 
- (int) getVal {return 3;} 

然後,我將每種類型的對象放到一個NSMutableArray中並取出一個。我想要做的是運行在適當的對象類型的GETVAL FUNC,但是當我把

id a = [allObjects objectAtIndex:0]; 
if ([a isKindOfClass:[TopClass class]]) 
{ 
    int i; 
    i = [a getVal]; 
} 

我首先得到一個有關多種方法稱爲GETVAL(警告可能是因爲編譯器不能確定實際的對象類型直到運行時)。但更嚴重的是,我也會得到一個錯誤「void value不應該被忽略,因爲它應該是」並且它不會被編譯。

如果我不嘗試使用[a getVal]的返回值,那麼它會編譯好的例如

[a getval]; //obviously no good if I want to use the return value 

如果在運行函數之前使用isMemberOfClass語句將對象轉換爲類,它也可以工作,例如,

if ([a isMemberOfClass:[BotClass]) i = [(BotClass*) a getVal]; 

但是當然,我不應該這樣做才能獲得我需要的功能嗎?否則,我將不得不爲每個單獨的子類聲明一個語句,如果我添加一個新的子類,則必須添加一個新行,而這又不利於方法覆蓋。

當然有更好的方法嗎?

+1

你不應該在Objective-C'-getSomething'中命名一個方法,你只需將它命名爲'-something'。 – 2010-06-10 20:00:41

回答

1

由於BotClass是MidClass,MidClass是TopClass,因此您可以將a的類型設置爲TopClass*

TopClass* a = [allObjects objectAtIndex:0]; 
if ([a isKindOfClass:[TopClass class]]) { 
    int i; 
    i = [a getVal]; 
} 

更好的方法是添加-getVal@interface#import它。然後編譯器會知道這種方法很可能會返回一個int並且即使aid也不會投訴。確保方法名稱不會與其他人重合。

(順便說一句,在ObjC,干將不會被命名爲-getFoo該公約是叫它-foo。)

+0

這是完全有道理的。我幾乎一直在嘗試,但從數組投射到a,顯然運行該方法只使用TopVal的方法。通過這種方式,我假定編譯器知道該期待什麼,但不會被強制轉換爲忽略子類。 非常感謝 – Rod 2010-06-10 20:16:32

+0

我想說,首先分配給TopClass變量,然後檢查對象是否真的是*這種類型是一個有趣的想法。它會工作,因爲它只是一個指針(你甚至可以使用NSArray * a,它會編譯時帶有警告,但在這種情況下工作),但它隱藏了代碼意圖。 :-) – Eiko 2010-06-10 20:18:24

0

你的代碼編譯沒有任何警告:

#import <Foundation/Foundation.h> 


@interface TopClass : NSObject 
{ 
} 

- (int) getVal; 

@end 

@interface MidClass : TopClass 
{ 
} 

- (int) getVal; 

@end 

@interface BotClass : MidClass 
{ 
} 

- (int) getVal; 

@end 


@implementation TopClass 

- (int) getVal { 
    return 1; 
} 

@end 

@implementation MidClass 

- (int) getVal 
{ 
    return 2; 
} 

@end 

@implementation BotClass 

- (int) getVal 
{ 
    return 3; 
} 

@end 


int main (int argc, const char * argv[]) { 
    NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; 
    NSMutableArray *array = [NSMutableArray array]; 

    [array addObject:[[[TopClass alloc]init]autorelease]]; 
    [array addObject:[[[MidClass alloc]init]autorelease]]; 
    [array addObject:[[[BotClass alloc]init]autorelease]]; 

    for (int objectNumber = 0; objectNumber < [array count]; objectNumber++) { 
     id a = [array objectAtIndex:objectNumber]; 
     if ([a isKindOfClass:[TopClass class]]) 
     { 
      int i = [a getVal]; 
      NSLog(@"%d",i); 
     }  
    } 

    [pool drain]; 
    return 0; 
} 

測試「isKindOfClass 「在這種情況下總是如此,因爲MidClass和BotClass繼承自TopClass。

您確定編譯器知道您調用的方法簽名嗎?