Objective-C中的覆盖方法

时间:2011-07-30 06:47:43

标签: objective-c

我对Objective-C比较陌生,我一直在考虑所有方法实际上都是虚拟的。我创建了这个小控制台程序:

#import <Foundation/Foundation.h>

@interface BaseClass : NSObject
{
}
- (void) virtualMethod: (NSInteger) integer;
@end

@interface DerivedClass : BaseClass
{
}
- (void) virtualMethod: (NSString *) string;
@end

@implementation BaseClass

- (void) virtualMethod: (NSInteger) integer
{
    NSLog(@"%ld", integer);
}
@end

@implementation DerivedClass

- (void) virtualMethod: (NSString *)string
{
    NSLog(@"%@", string); // Program received signal: "EXC_BAD_ACCESS". -- as expected
}
@end

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

    NSArray *arr = [NSArray arrayWithObjects: [BaseClass new], [DerivedClass new], nil];
    for (int i = 0; i < arr.count; i++) 
    {
        BaseClass *b = (BaseClass *)[arr objectAtIndex: i];
        [b virtualMethod: i];
    }
    NSLog(@"\n\nTapos na!\n\n");

    [pool drain];
    return 0;
}

正如预期的那样,我在派生的EXC_BAD_ACCESS中得到virtualMethod:,因为毕竟它不需要整数,它需要NSString *作为参数。虚拟机制基于选择器,似乎不考虑签名。

我的问题:语言中是否有某些东西可以防止这种覆盖发生不同的签名?有些方法告诉编译器virtualMethod:应该始终具有相同的签名,或者如果签名不匹配,会使编译器发出某种提示,警告或错误?

我知道一个好的程序员总是指出一个方法应该具有的类型的名称,但这是一个约定,而不是语言规则。我问的是编译器功能,以防止问题发生。

2 个答案:

答案 0 :(得分:7)

嗯,有...但你可能不想使用它。在Xcode中有一个名为“Strict Selector Matching”的构建设置(它以-Wstrict-selector-match的形式传递给编译器)。如果编译器找到两个具有不同参数或返回类型的选择器,这将警告您。

不幸的是,即使类型不同但兼容,警告也会出现。因此,如果你打开它,你会得到一堆虚假警告的地方,你不会期望是模棱两可的。不过,请随意尝试一下。

如果您想了解更多信息,Matt Gallagher写了a nice post about it。与此同时,我担心这里没有一个很好的解决方案。

答案 1 :(得分:0)

当前版本的XCode会给您以下警告:

“'[method]'实现中的冲突参数类型:'[需要的类型]'vs'[你错误选择的类型]'”