views:

46

answers:

3

I'm trying to declare a variable inside an if statement. If the result of a query is YES then the object will be of one type, otherwise it will be of another type. A bit like this...

if (YES) {
          ObjectTypeA *object = [[ObjectTypeA] alloc] init];
}

else {
      ObjectTypeB *object = [[ObjectTypeB] alloc] init];
}

Once that's done I want to use object with the same methods no matter what type it is. I tried declaring object as an id before the if statement but get an error: member reference type 'struct objc_object *' is a pointer; maybe you meant to use '->'?

I also tried declaring both to be separate objects outside the if and then make the pointer point to whichever it was once I knew. That wouldn't work either.

I know that the compiler is trying to protect me from myself by doing this but in this circumstance I need a way round it please.

Thanks.

+1  A: 

I think this code should work well:

id obj = nil;

if (YES) {
   obj = [[ObjectTypeA] alloc] init];
} else {
   obj = [[ObjectTypeB] alloc] init];
}

[obj performSelector:@selector(YOUR_METHOD) withObject:YOUR_OBJECT];
vodkhang
It might be useful to mention the other mistake in the questioner's code, in that the variables defined inside the the if/else will be out of scope outside the if/else.
Jasarien
I am not sure but the explanation says something about declaring outside : " also tried declaring both to be separate objects outside the if and then make the pointer point to whichever it was once I knew. That wouldn't work either." I don't really get it so I write again
vodkhang
You could call the method directly, in this case `the performSelector:` is not neccessary.
Sven
I tried declaring them outside as suggested here but had an error telling me member reference type 'struct objc_object *' is a pointer; maybe you meant to use '->'?. This happened anyplace I tried to call a method on object.
Mark Reid
Tried this one and it still displays the error I mention above when I try and call methods based on the object.
Mark Reid
what, are you sure? It is impossible, what object type are you trying to call? Or are you calling an instance variable/property? Please give me more codes for the method as well as both class A and B declaration
vodkhang
And don't use the name "object" for the variable name, please
vodkhang
A: 

You want dynamic typing :)

The way around this is to declare a third object that both of these inherit from

OR

You could use the adapter pattern and create an object that accepts both of these objects as a member and then wrap the functions you wish to call into that object

good luck!

--> These are genral OO solutions; I'm not a Objective-C developer

Ayubinator
+3  A: 

The most common pattern for this problem in Cocoa/Cocoa Touch is to define a protocol.

A protocol is a collection of methods that can be implemented by any object.

If you make ClassA and ClassB conform to a protocol containing the methods you need them to respond to then you don't need to worry about which type of object you get.

The idea is "if it looks like a duck and quacks like a duck, then it's probably a duck".

You can use dynamic typing and create your objects depending on the outcome of your query, but ensure that the resulting object conforms to a particular protocol, like so:

id <MyProtocol> myObject;

if (YES)
    myObject = [[ClassA alloc] init];
else
    myObject = [[ClassB alloc] init];

[myObject myMethod];
[myObject release];
Jasarien