我对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:
应该始终具有相同的签名,或者如果签名不匹配,会使编译器发出某种提示,警告或错误?
我知道一个好的程序员总是指出一个方法应该具有的类型的名称,但这是一个约定,而不是语言规则。我问的是编译器功能,以防止问题发生。
答案 0 :(得分:7)
嗯,有...但你可能不想使用它。在Xcode中有一个名为“Strict Selector Matching”的构建设置(它以-Wstrict-selector-match
的形式传递给编译器)。如果编译器找到两个具有不同参数或返回类型的选择器,这将警告您。
不幸的是,即使类型不同但兼容,警告也会出现。因此,如果你打开它,你会得到一堆虚假警告的地方,你不会期望是模棱两可的。不过,请随意尝试一下。
如果您想了解更多信息,Matt Gallagher写了a nice post about it。与此同时,我担心这里没有一个很好的解决方案。
答案 1 :(得分:0)
当前版本的XCode会给您以下警告:
“'[method]'实现中的冲突参数类型:'[需要的类型]'vs'[你错误选择的类型]'”