Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Objective-C Pointer to class that implements a protocol

I have three classes which implement the same protocol, and have the same parent class which doesn't implement the protocol. Normally I would have the protocol as pure virtual functions in the parent class but I couldn't find an Objective-C way to do that.

I want to utilize polymorphism on these subclasses by declaring pure virtual functions in the superclass then have the children implement those functions. However the only Objective-C way I've found to do this is to have each child explicitly decide to implement a protocol, when I do it this way the superclass doesn't know the children will implement that protocol so there are compile time warnings all over the place.

Some pseudo-code if that didn't make sense:

@interface superclass: NSObject
{}

@interface child1: superclass<MyProtocol>
{}

@interface child2: superclass<MyProtocol>
{}

The consumer of these classes:

@class child1
@class child2
@class superclass

@interface SomeViewController: UIViewController
{
    child1 *oneView;
    child2 *otherView;
    superclass *currentView;
}

-(void) someMethod
{
    [currentView protocolFunction];
}

The only nice way I've found to do pure virtual functions in Objective-C is a hack by putting [self doesNotRecognizeSelector:_cmd]; in the parent class, but it isn't ideal since it will cause runtime errors rather than compile time.

like image 489
Winder Avatar asked Apr 18 '10 23:04

Winder


People also ask

How do you make an optional protocol in Objective-C?

Optional Protocol methods can be marked as optional using the @optional keyword. Corresponding to the @optional modal keyword, there is a @required keyword to formally denote the semantics of the default behavior. You can use @optional and @required to partition your protocol into sections as you see fit.

Can Objective-C protocols have properties?

You can have properties in a protocol, provided every class that conforms to your protocol have a corresponding @synthesize for that property, or provide a getter and setter. But with a class category you generally can't add instance variables to a class.

WHAT IS interface and implementation in Objective-C?

Interface and Implementation In Objective C, the file where the declaration of class is done is called the interface file and the file where the class is defined is called the implementation file.


3 Answers

Objective-C developers commonly use dynamic checking rather than compile-time checking in these situations because the language and the frameworks support it so well. So for example, you could write your method like this:

- (void)someMethod
{
    // See if the object in currentView conforms to MyProtocol
    //
    if ([currentView conformsToProtocol:@protocol(MyProtocol)])
    {
        // Cast currentView to the protocol, since we checked to make
        // sure it conforms to it. This keeps the compiler happy.
        //
        [(SuperClass<MyProtocol> *) currentView protocolMethod];
    }
}
like image 111
jlehr Avatar answered Oct 21 '22 17:10

jlehr


I was able to get the compiler to warn me correctly by making the superclass *currentView property look like this:

@property (nonatomic, retain) superclass<MyProtocol> *currentView;
like image 29
Winder Avatar answered Oct 21 '22 17:10

Winder


Alternatively you can use the following

if ([unknownObject conformsToProtocol:@protocol(MyProtocol)])
   [unknownObject performSelector:@selector(methodInProtocol)];

instead of the following if you just want to suppress the warning.

if ([unknownObject conformsToProtocol:@protocol(MyProtocol)])
   [unknownObject methodInProtocol];  // will cause warning

performSelector: will only work if the number of arguments is zero or one. More flexible invocations can be achieved with NSInvocation.

like image 3
NSSplendid Avatar answered Oct 21 '22 17:10

NSSplendid