1

嗨,我正在寻找一种方法来在 Cocoa 上的 Objective-C 中强制执行运行时类型检查或此类事情。

这是我的代码示例。我预计有关错误分配变量“b”的运行时错误。但事实并非如此。编译并执行,没有任何错误。

#import <Foundation/Foundation.h>

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

 NSArray* a = [NSArray arrayWithObject: @"TEST"]; 
 NSURL* b = [a objectAtIndex:0]; 

    NSLog(@"Is this URL? %i", [b isKindOfClass:NSURL.class]);
    [pool drain];
    return 0;
}

// Console log after program execution:
// 2010-01-11 10:25:02.948 Type Checking[98473:a0f] Is this URL? 0

我很惊讶没有运行时类型检查。因为我使用了所有高级语言,如 VB、C#、Java、ActionScript……我不懂 C 等低级语言,所以我不确定这是正确的方法……真的很难弄清楚为什么没有编译或运行时错误。但我开始将其理解为现实 C 世界中的自然规则。但是更强大的类型检查会对我有很大帮助。即使只在调试会话中。有没有办法做到这一点?

如果没有运行时类型检查,我必须使用什么样的编码和调试策略来处理错误的类型值?运行时类型检查之间的权衡是什么?

4

3 回答 3

2

嗯,有运行时类型检查,但它会在稍后发生。我假设您在尝试将 NSString 实例放入 NSURL* 变量时会出现某种异常。相反,当您尝试在您的 NSString 实例上调用任何特定于 NSURL 的方法时,您会得到异常。

例如,如果你尝试[b isFileURL]你会得到一个异常,比如“NSString 不响应选择器'isFileURL'”。

理解为什么在您的示例中没有编译时类型检查也很重要。具体来说,缺乏编译时类型检查是类型的一个独特而重要的属性id,这就是 NSArray 的-objectAtIndex:返回值。

于 2010-01-11T02:01:22.603 回答
1

Objective-C 确实对消息参数和返回类型进行了编译时类型检查,但它比许多其他语言更宽松。一个主要区别是 NSArray 和 NSDictiomary 等集合类是通用的。您可以将任何类型的对象放入 NSArray - 元素不必是相同的类型。因此,添加或访问元素时没有类型检查。

变量赋值没有运行时类型检查。我相信这是一个性能捷径。一般来说,这不是什么大问题。如果错误类型的值被分配给一个变量,它最终会收到一条它不理解的消息,这会生成一个非常有用的错误消息。

于 2010-01-11T02:36:07.027 回答
0

当类型错误时,NSObject 框架通常会大惊小怪,但您可以手动检查类型并抛出异常:

if (![obj isKindOfClass:SomeObjectClass.class])
  [NSException raise:@"BadTypeException"
    format:@"Bad type at line %d", (int)__LINE__];
[obj xyz];

...

if (![obj conformsToProtocol:@protocol(SomeProtocol)])
  [NSException raise:@"BadTypeException"
    format:@"Bad type at line %d", (int)__LINE__];
[obj abc];

编辑:删除了上一节声称对不存在的方法的调用返回 nil 或零;正如 Mark Bessey 所说,如果非 nil 对象未实现方法,则会引发异常(不返回零)。

于 2010-01-11T02:26:25.347 回答