1

Is there a cast keyword in Objective-C like C# (as):

Foo bar = new Foo();
Foo tmp = bar as Foo;

Is this possible in Objective-C?

afuzzyllama
  • 6,538
  • 5
  • 47
  • 64
Nick Turner
  • 927
  • 1
  • 11
  • 21

3 Answers3

6

There is no direct equivalent of as in Objective-C. There is regular type casting (C-style).

If you want to check the type of the object, be sure to call isKindOfClass:.

To write the equivalent of:

Foo bar = new Foo();
Foo tmp = bar as Foo;

You'd write:

Foo *bar = [Foo new];
Foo *tmp = ([bar isKindOfClass:[Foo class]]) ? (Foo *)bar : nil;

You could always write this up as a category like:

@implementation NSObject (TypeSafeCasting)

- (id) asClass:(Class)aClass{
   return ([self isKindOfClass:aClass]) ? self : nil;
}

@end

Then you could write it like:

Foo *bar = [Foo new];
Foo *tmp = [bar asClass:[Foo class]];
Jason Whitehorn
  • 13,585
  • 9
  • 54
  • 68
  • 3
    Note that this type of meta-programming in Objective-C is generally a "code smell" indicating that your architecture is far afield of the norms of the language and frameworks. – bbum Dec 13 '12 at 23:26
  • @bbum, just to clarify, you are not arguing against the use of categories, but rather the need for the `as` feature from C#? – Jason Whitehorn Dec 14 '12 at 00:46
  • Categories generally suck, too. They are often a crutch that enables poor design. – bbum Dec 14 '12 at 12:04
1

No, no such keyword exists but you could emulate such behavior with a macro.

#define AS(x,y) ([(x) isKindOfClass:[y class]] ? (y*)(x) : nil)

@interface Foo : NSObject
@end
@implementation Foo
@end

int main(int argc, char *argv[])
{
    @autoreleasepool {

        Foo *bar = [[Foo alloc] init];
        Foo *tmp = AS(bar, Foo);

        NSLog(@"bar as Foo: %@", tmp);

        bar = [NSArray array];
        tmp = AS(bar, Foo);
        NSLog(@"bar as Foo: %@", tmp);
    }
}

Outputs:

bar as Foo: <Foo: 0x682f2d0>
bar as Foo: (null)

I would suggest just checking isKindOfClass: directly rather than using a poorly named macro like AS. Also if the first paramater of the macro is an expression e.g ([foo anotherFoo]) it will be evaluated twice. That could lead to performance issues or other issues if anotherFoo has side effects.

Joe
  • 56,979
  • 9
  • 128
  • 135
-1

Typecasting (it's just C):

Foo *foo = [[Foo alloc] init];
Bar *bar = (Bar *)foo;

NB: you can shoot yourself in the foot with this, be careful.

  • Didn't downvote, but this isn't the same thing. `as` checks RTTI to verify type compatibility. c# also has c-style casting, so this isn't really what was being asked. – Donnie Dec 13 '12 at 21:53
  • @Donnie [I know that as well.](http://stackoverflow.com/questions/10557756/objective-c-dynamic-cast/10557838#10557838) –  Dec 13 '12 at 21:55
  • 1
    I am really confused as to why this is getting up-votes, this answer is incorrect. – Jason Whitehorn Dec 14 '12 at 00:28
  • 1
    @H2CO3, I don't think you understand the `as` keyword. The `as` keyword will return `nil` if the object being casted is not of the appropriate class. Using your example I can cast an `NSNumber` to an `NSString`. – Jason Whitehorn Dec 14 '12 at 14:51
  • @JasonWhitehorn check the link I replied to Donnie with. –  Dec 14 '12 at 15:48