Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Defining categories for protocols in Objective-C?

In Objective-C, I can add methods to existing classes with a category, e.g.

@interface NSString (MyCategory) - (BOOL) startsWith: (NSString*) prefix; @end 

Is it also possible to do this with protocols, i.e. if there was a NSString protocol, something like:

@interface <NSString> (MyCategory) - (BOOL) startsWith: (NSString*) prefix; @end 

I want to do this since I have several extensions to NSObject (the class), using only public NSObject methods, and I want those extensions also to work with objects implementing the protocol .

To give a further example, what if I want to write a method logDescription that prints an object's description to the log:

- (void) logDescription {     NSLog(@"%@", [self description]); } 

I can of course add this method to NSObject, but there are other classes that do not inherit from NSObject, where I'd also like to have this method, e.g. NSProxy. Since the method only uses public members of protocol , it would be best to add it to the protocol.

Edit: Java 8 now has this with "virtual extension methods" in interfaces: http://cr.openjdk.java.net/~briangoetz/lambda/Defender%20Methods%20v4.pdf. This is exactly what I would like to do in Objective-C. I did not see this question earning this much attention...

Regards, Jochen

like image 795
Jochen Avatar asked Oct 05 '09 17:10

Jochen


People also ask

How do you declare a protocol in Objective-C?

In Objective-C, you add the protocol name in angle brackets beside the class interface declaration. MyClass is declaring that it conforms to SampleProtocol below. MyClass will also have to provide an implementation for “someMethod” in the implementation file because it is a required protocol method.

What is the difference between category and extension in Objective-C?

Category and extension both are basically made to handle large code base, but category is a way to extend class API in multiple source files while extension is a way to add required methods outside the main interface file.


1 Answers

Short answer: No.

Long answer: how would this work? Imagine you could add methods to existing protocols? How would this work? Imagine we wanted to add another method to NSCoding, say -(NSArray *) codingKeys; This method is a required method that returns an array of the keys used to encoding the object.

The problem is that there are existing classes (like, say NSString) that already implement NSCoding, but don't implement our codingKeys method. What should happen? How would the pre-compiled framework know what to do when this required message gets sent to a class that does not implement it?

You could say "we can add the definition of this method via a category" or "we could say that any methods added via these protocol categories are explicitly optional". Yes, you could do this and theoretically get around the problem I've described above. But if you're going to do that, you might as well just make it a category in the first place, and then check to make sure the class respondsToSelector: before invoking the method.

like image 143
Dave DeLong Avatar answered Sep 27 '22 18:09

Dave DeLong