Question

I'm using a framework which defines and uses 'ClassA', a subclass of NSObject. I would like to add some variables and functionality so naturally I created 'ClassB', a subclass of 'ClassA'

Now my problem is this. Many of the methods within this framework return instances of 'ClassA' which I would like to cast to my subclass.

For example take this method:

- (ClassA *)doSomethingCool:(int)howCool

Now in my code I try this:

ClassB * objB;
objB = (ClassB *)doSomethingCool(10); 

NSLog(@"objB className = %@", [objB className]);

This runs just fine. No compile or runtime errors or anything. But what is really odd to me is the output:

>> "objB className = ClassA"

The casting obviously failed. Not sure what's happened at this point... objB is typed as 'ClassB', but it's className is 'ClassA' and it won't respond to any 'ClassB' methods.

Not sure how this is possible... Anyone know what I am doing wrong here?

I found a similar post which is exact opposite of what I'm asking here

Was it helpful?

Solution

Casting object variables in Objective-C is usually a mistake (there are a few cases where it's right, but never for this sort of thing). Notice that you aren't casting an object — you're casting a pointer to an object. You then have a pointer of type ClassB*, but it still points to the same instance of ClassA. The thing pointed to hasn't changed at all.

If you really want to convert instances of ClassA to ClassB, you'll need to write a ClassB constructor method that can create a ClassB instance from a ClassA. If you really need to add instance variables, this might be your best choice.

As Jason said, though, it's often a good idea to try a category first.

OTHER TIPS

You can't just cast a super class to its subclass. It doesn't actually implement any of your added variables/properties or methods. As soon as you try to message it with a method you define on your subclass, you are going to get a runtime exception and your application is going to quit. You can only safely cast in one direction: from more specific to more general. I.e., you can cast our ClassB to a ClassA safely, using only the methods and properties of ClassA, but not the other way around.

Think of it this way: you have a Car (the parent class) and a FourDoorSedan (the subclass). Every car has an engine and two doors. Now, let's say you are getting a car from somewhere, and that's really all you know about it. You tell the operator, that car is a FourDoorSedan, but in fact it turns out it's not. So when the operator does something like: openBackPassengerDoor, what happens? There are only two doors!! It's the same here.

If you just want to add a little functionality to ClassA, check out Objective-C Categories, they're probably what you want and no casting will be required. Read the documentation carefully, however, because they are not without their caveats.

If you just want to add a method to existing objects, subclassing is not the correct way. You can add method to existing classes (and their instances) using a language feature called category.

Example:

//"ClassA+doSomethingCool.h"
@interface ClassA (doSomethingCool)
- (ClassA *)doSomethingCool:(int)howCool;
@end


//"ClassA+doSomethingCool.m"
@implementation ClassA (doSomethingCool)
- (ClassA *)doSomethingCool:(int)howCool
{

}
@end

Casting doesn't convert from one type of object to another. You can't force some library to change type of object and create another type of objects unless it utilizes some factory pattern.

What happens when you call one of your subclass methods on the returned object?

ClassB * objB;
objB = (ClassB *)doSomethingCool(10);
[objB subClassMethod];

Obj-C is pretty free and lose with types, you don't even need to know the type before hand, eg. you could change all of your ClassB references to id. I know it's safer to know you have the expected type but if your code is correct it shouldn't matter.

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