Search code examples
iosobjective-cooppolymorphismobjective-c-category

How method calls are resolved by argument in category classes in Objective C?


I have a root class and number of child classes. I have also a DataManager class that is supposed to hold static methods in various categories that act on particular child of this root class.

Let's say for root class R, Child classes are C1 & C2.

For C1, I have category called DataManager+C1.
For C2, I have category called DataManager+C2.

I have a base DataManager class where I have declared this method - from where it is accessed everywhere - and there are no other declarations:

//DataManager.h
+ (NSDictionary *) Method1 : (DataModelRoot*) R;
//Note that R is my root class. Individual class implementations belong to DataManager+C1.m, DataManager+C2.m etc.

Implementation of Method1 lies in DataManager+C1 as well as DataManager+C2.

But I fail to see polymorphic behaviour.

That is, when Method1 invocation of DataManager+C2 is expected, the one inside DataManager+C1 is invoked, although the call itself initiates from DataManager+C2 source file. (the caller can be any DataManager category though - this is one extreme case).

How do number of categories on objects lying in same class hierarchy resolve function calls?

PS: Note again, that the above method Method1 is ONLY EXPOSED in .h file of one class (plain DataManager.h) with root class as the argument. I assume this will ensure proper invocation using child object type, but it's failing.


Solution

  • Objective-C supports polymorphism on class methods when the target of the message actually is polymorphic.

    Example:

    [DataManager Method1:nil];
    

    ... would not select a target polymorphically because the target is the concrete class DataManager. It would just always send the message to the implementation in DataManager.

    If, on the other hand, the target is a dynamically determined, there's actual polymorhism as expected. A typical example is an instance method implementation in the same class or a subclass:

    - (void)foo
    {
        [[self class] Method1:nil];
    }
    

    This would indeed call the closest overridden implementation of Method1: and thus granting polymorphic behavior.

    Sidenote: The behavior described above is not affected by categories. Provided there are no name clashes, categories have little influence on how messages are dispatched.