Question

Hi I'm finding a way to enforce runtime type checking or such things in Objective-C on Cocoa.

This is my code sample. I expected runtime error about wrong assignment to variable 'b'. But it wasn't. Compiled and executed without any error.

#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

I surprised about there is no runtime type checking is there. Because I used all high level languages like VB, C#, Java, ActionScript... I don't know low-level language like C, so I can't sure this is right way... It was really hard to figuring out why there is no compile or runtime error. But I'm getting to understand this as a natural rule in real C world. But more strong type checking will help me a lot. Even only in debugging session. Is there any way to do this?

And if there is no runtime type checking, what kind of coding and debugging strategy do I have to use about wrong typed values? And what's the trade off between runtime type checking is or isn't?

Was it helpful?

Solution

Objective-C does have compile-time type checking for message arguments and return types, but it is somewhat looser than many other languages. One major difference is that collection classes like NSArray and NSDictiomary are generic. You can put any type of object into an NSArray - the elements don't have to be the same type. Therefore, there's no type-checking when adding or accessing elements.

There is no run-time type checking for variable assignment. I believe that is a performance short-cut. In general, it's not much of an issue. If the wrong type of value gets assigned to a variable, it'll eventually get sent a message it doesn't understand, which generates a pretty useful error message.

OTHER TIPS

Well, there is run-time type checking, but it happens a little later. I assume you're expecting some sort of exception when you try to put an NSString instance into a NSURL* variable. Instead, you'll get the exception when you try to call any NSURL-specific methods on your NSString instance.

For example, if you try [b isFileURL] you'll get an exception like "NSString does not respond to selector 'isFileURL'".

It's also important to understand why there's no compile-time type checking in your example. Specifically, the lack of compile-time type checking is a unique and important property of the id type, which is what NSArray's -objectAtIndex: returns.

The NSObject Framework will often kick up a fuss when the type is wrong but you can manually check for the type and throw an exception:

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];

Edit: Removed previous section claiming that calls to non-existent methods return nil or zeroes; as Mark Bessey says, an exception is thrown (not zero returned) if a non-nil object does not implement a method.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top