Understanding Protocols and Sub-Classing - objective-c

I am in the process of creating a UITableViewController sub-class (call it "MyTableViewClass", that would ultimately be sub-classed for specific table view controllers (call it "MySpecificTableViewClass". Ideally I want some methods that are in the MySpecificTableViewClass to be "required" ie. have the developer interface say "implementation is not complete". Is there a way to do that without having to declare in the protocol in MyTableViewClass?
MyTableViewClass.h
#import <UIKit/UIKit.h>
#class MyTableViewClass;
#protocol MyTableViewClassProtocol <NSObject>;
-(void) fooBar;
#end
#interface MyTableViewClass : UITableViewController <NSFetchedResultsControllerDelegate, MyTableViewClassProtocol>
....
This will indicate in my implementation of MyTableViewClass that I have "forgotten" to implement fooBar. I think I can just handle that with a stub method (is that the best way?).
MySpecificTableViewClass.h
....
#import "MyTableViewClass.h"
#interface MySpecificTableViewClass : MyTableViewClass
....
In the implementation of MySpecificTableViewClass - no warning shows that I am missing
-(void) fooBar
If I change MySpecificTableViewClass.h to
....
#import "MyTableViewClass.h"
#interface MySpecificTableViewClass : MyTableViewClass <MyTableViewClassProtocol>
....
Then I do get the warning, but remembering to define the protocol, seems counter intuative, or am I completely missing something?

I haven't found a great way to implement this other than to put in stubs and call NSAssert() in them to catch (at runtime) any unimplemented methods. Objective-C doesn't have the concept of an abstract class.
That said, and while I've used this pattern myself, often it is better to rethink your design and use the Strategy pattern and protocols. That is, instead of having an abstract MyTableViewClass, create a MyTableViewHandler that is a subclass of NSObject and contains whatever special logic you need. Then your table view controllers can be direct subclasses of UITableViewController and delegates of MyTableViewHandler. As a delegate, the protocol can be enforced. And this creates a simpler and more flexible object model. It's not always appropriate, and abstract classes have their place, but do consider the Strategy pattern before you jump to pure inheritance. It often works better.

As MyTableViewClass is already implementing the protocol, its subclasses will get those implementations available for them, It means subclasses are also kind of implementing them. You can change/extend the implementations in your subclasses.

Related

Who does what with protocols in objective-c?

Trying to understand protocols and their use... having a hard time of it. The more I read, the less I am able to even formulate questions about them. I've read the statement "a protocol is a contract" a hundred times, but it just doesn't click.
I "only" want to develop really simple apps, so assume that I would not myself create a protocol for any of my classes.
I do want to use Apple's Scenekit framework, for example, and understand that I am required to implement some methods to do this - for example the SCNSceneRendererDelegate. The compiler enforces this, and it knows to do that because in my header file I have inserted:
#interface AAPLGameViewController : UIViewController <SCNSceneRendererDelegate>
the bit between the angle brackets specifically.
For the prototypes of the functions I have to implement, I go look for a
#protocol
...
#end
section in the SCNSceneRendererDelegate header file.
But now I've come across some #protocol sections (e.g. in the UIApplication header file) that contain #properties!! I thought #protocol was only about implementing certain methods, what is a property doing there?
I also came across in one of the answers here that specifying a protocol name when creating an instance of an object allows me to use objects that I know nothing about. I would be very grateful to get a few simple practical examples of where this would be useful.
And finally, in Java, the counterpart to (Obj-C) #protocols are called interfaces. Is there a counterpart in Java to (Obj-C) #interface?
Thanks much, cheers.
Adhering to a protocol tells other classes that your class has a specific set of characteristics. Usually protocols are used to define what methods a specific class should have so that it can be the delegate of another class, meaning the class adopting the protocol is guaranteed to have defined the required methods that the delegate class will call in a callback. If the protocol defines a property, it simply means any classes adopting the protocol are expected to also have that property. For example:
#protocol MyProtocol <NSObject>
#required
#property (readonly) NSString *title;
#optional
- (void) someMethod;
#end
I can now define a method anywhere that takes an object conforming to MyProtocol and safely access the title property because it is guaranteed to exist for all classes adopting MyProtocol.
-(void)printTitleOfObject:(id<MyProtocol>)object {
NSLog(#"%#", object.title);
}
So even though id can be any object, since we know that it conforms to our protocol we know that it has the title property. When people say "a protocol is a contract", what they mean is even if we don't know specifically what class is adopting the protocol, we know it at least has the methods and properties listed as required in the protocol. Specifying a protocol for a class allows us to know some information about it, even if we don't know what class it is.
Apple has written documentation for protocols they've written, like the SCNSceneRendererDelegate you mentioned in your question.
But now I've come across some #protocol sections (e.g. in the
UIApplication header file) that contain #properties!! I thought
#protocol was only about implementing certain methods, what is a
property doing there?
Properties are methods. A property declaration is simply a declaration for a getter-setter method pair (or if a readonly property, just a getter method), and allows the compiler to turn a dot notation access into a call to this getter and setter. That's all a property is. How the getter/setter is implemented (whether manually implemented or synthesized), and whether it reflects an underlying value or not (or is computed from other things) are private implementation details of the getter/setter methods.

Implement protocol through methods declared in superclass?

I'm wondering if it is possible, in a certain subclass, to "recognise" methods declared in it's superclass as implementations of methods declared in a protocol the subclass adheres to, given that they have the same signatures.
It kind of gets hard to even formulate this, that's why any searches I made turned out fruitless so far.
But let me make the case with an example for better understanding.
Protocol:
#protocol TheProtocol <NSObject>
- (void)theProtocolMethod;
#end
Superclass:
// Superclass does not adhere to TheProtocol
#interface TheSuperClass : NSObject
- (void)theProtocolMethod;
#end
#implementation TheSuperClass
- (void)theProtocolMethod
{
// stuff
}
#end
Subclass:
// SubClass adheres to TheProtocol but does not implement it's methods
// since they are implemented in the class it is subclassing. Is this OK?
#interface TheSubClass : TheSuperClass <TheProtocol>
#end
#implementation TheSubClass
#end
Is this anywhere close to being "OK"?
What about the case TheSubClass was in fact a category of TheSuperClass (declaring adherence to TheProtocol) and not a subclass?
A bit more context:
It's a scenario involving Core Data. I need to publish an accessor defined in an Entity Class, in a Protocol that will be used in a separate Framework for developing plugins for my app. The Protocol itself is fully implemented by a Category of the Core Data Entity Class, except for said accessor which is implemented in the Entity Class itself, hence my question.
In absolute terms, this is perfectly legal. Calling -theProtocolMethod on an instance of TheSubClass would indeed invoke TheSuperClass implementation if TheSubClass itself doesn't implement it. You could even call [super theProtocolMethod] in your subclass implementation, if you wanted.
If TheSubClass was a category on TheSuperClass, the superclass implementation would still be called. However, implementing -theProtocolMethod in the category would replace the super class implementation, so you have to be careful here.
Subjectively, in code-design terms, it's maybe a little odd. You essentially have two separate declarations of the same method to manage, which could potentially cause problems if you tried to refactor. I'm guessing the superclass in your case is a library class that you cannot change. Otherwise, I can't see why TheSuperClass shouldn't just conform to the protocol, rather than declare the method separately.
In theory you're saying the superclass is already compliant with the protocol.
If the compiler complains, you can implement wrapper methods in your subclass that simply call super and return any return value from the call to super.

Is it a good practice to force developer to comply with a protocol in objective C?

I am developing a simple set of reusable code. I have created a protocol to group a set of methods and ask the user at run time for data.
I think that setting a delegate would be mandatory. Can I force the developer at runtime to set the delegate by throwing an assert stating the reason?
Is this a good practice to enforce the user of my classes by using asserts? Does it have a design level flaw?
First the "good practice" question:
Don't make methods required unless they actually are.
Don't make methods optional if they aren't.
Not a critical one, more of an opinion
Provide a method initWithDelegate: if a delegate is required
I often come across data structures where I don't know that there is a delegate pattern until I investigate. With the specific init method, I'm made aware of it earlier.
You can cause warnings at compile time by simply adding the #required indicator to your protocol:
#protocol SuperAwesomeProtocol <NSObject>
#required
-(void) requiredMethod1;
-(void) requiredMethod2;
#optional
-(void) optionalMethod1;
-(void) optionalMethod2;
#end
//and making your delegate specific:
#property (nonatomic, assign) id<SuperAwesomeProtocol> delegate;
You can still cause runtime asserts with:
if (!delegate || ![delegate respondsToSelector:#selector(requiredMethod1)])
{
//Assertion failure
}
Yes I think it is good practice to use protocol in the application..
Protocols declare methods that can be implemented by any class.
Below are the situation in which use of protocol is good.
To declare methods that others are expected to implement
To declare the interface to an object while concealing its class
To capture similarities among classes that are not hierarchically
related

How do I implement a protocol generically with a category?

How do you decorate a class with some generic implementation of a protocol?
Sorry for what might be an obvious question. I'm new to objective c and so am still treading water just a little bit.
I've got a protocol for which I want a generic implementation:
#protocol SelectableElement <NSObject>
#property BOOL selected;
#end
I've got a couple of objects that I want to be selectable:
#interface Widget : NSObject <SelectableElement>
#end
#interface Duhicky : NSObject <SelectableElement>
#end
What I'd like to do is to write the implementation of the protocol once, and make sure that both objects implement it that way.
I don't think that I can write a generic category and bind it to both, so I guess one way of doing it is to add implement the category on the common class NSObject:
#implementation NSObject (Selectable)
- (BOOL)selectable
{
if (![self conformsToProtocol:#protocol(SelectableElement)]) return;
return YES; // Use associative storage for this?
}
- (void)setSelectable:(BOOL)selectable
{
if (![self conformsToProtocol:#protocol(SelectableElement)]) return;
// set this associatively?
}
#end
Of course, I can't define a property variable to do this, I would need to use the associative object store... which I've not demonstrated here.
Is this the only way of adding selectable behaviour generically to anything that implements the selectable element protocol? Or is there a more obvious way that I'm missing?
I can of course use inheritance to implement this simple example, but that would only work for implementing a single protocol in this way. Is this approach that I've suggested considered a natural fit, or is it a hack?
Joe
Make a class that implements the protocol ie. SelectableObject and then make the Widget and Duhicky classes inherit SelectableObject.
It sounds you want something like a Mixin in Ruby. Unfortunately, this is not possible on the language level in Objective-C. The only way to share behaviour is through inheritance.
That said, you could do some tricks with the Objective-C runtime to achieve what you want. It's probably not a good idea to work against the language you're using, but if you want to explore this option have a look here: http://cocoadev.com/wiki/MethodSwizzling
Sadly, this is one of those cases where inheritance is a particularly bad fit for the problem.
However, you can see this (ab)use of inheritance in the Cocoa frameworks (NSResponder or UIResponder). You'll run up against problems if you need to make an object selectable if you don't control the inheritance structure (some object in an external framework).
Your category on NSObject will work, and I would consider it preferable in this case. At first glance it seems heavy-handed for every object to carry around these methods, but the performance penalty is small due to caching in the method lookup mechanism.

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
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.
While it's true that you can't define categories for protocols (and wouldn't want to, because you don't know anything about the existing object), you can define categories in such a way that the code only applies to an object of the given type that has the desired protocol (sort of like C++'s partial template specialization).
The main use for something like this is when you wish to define a category that depends on a customized version of a class. (Imagine that I have UIViewController subclasses that conform to the Foo protocol, meaning they have the foo property, my category code may have need of the foo property, but I can't apply it to the Foo protocol, and if I simply apply it to UIViewController, the code won't compile by default, and forcing it to compile means someone doing introspection, or just screwing up, might call your code which depends on the protocol. A hybrid approach could work like this:
#protocol Foo
- (void)fooMethod
#property (retain) NSString *foo;
#end
#implementation UIViewController (FooCategory)
- (void)fooMethod {
if (![self conformsToProtocol:#protocol(Foo)]) {
return;
}
UIViewController<Foo> *me = (UIViewController<Foo>*) self;
// For the rest of the method, use "me" instead of "self"
NSLog(#"My foo property is \"%#\"", me.foo);
}
#end
With the hybrid approach, you can write the code only once (per class that is supposed to implement the protocol) and be sure that it won't affect instances of the class that don't conform to the protocol.
The downside is that property synthesis/definition still has to happen in the individual subclasses.
extObjC has the NEATEST stuff you can do with Protocols / Categories... first off is #concreteprotocol...
Defines a "concrete protocol," which can provide default implementations of methods within protocol.
An #protocol block should exist in a header file, and a corresponding #concreteprotocol block in an implementation file.
Any object that declares itself to conform to this protocol will receive its method implementations, but only if no method by the same name already exists.
MyProtocol.h
#protocol MyProtocol
#required - (void)someRequiredMethod;
#optional - (void)someOptionalMethod;
#concrete - (BOOL)isConcrete;
MyProtocol.m
#concreteprotocol(MyProtocol) - (BOOL)isConcrete { return YES; } ...
so declaring an object MyDumbObject : NSObject <MyProtocol> will automatically return YES to isConcrete.
Also, they have pcategoryinterface(PROTOCOL,CATEGORY) which "defines the interface for a category named CATEGORY on a protocol PROTOCOL". Protocol categories contain methods that are automatically applied to any class that declares itself to conform to PROTOCOL." There is an accompanying macro you also have to use in your implementation file. See the docs.
Last, but NOT least / not directly related to #protocols is
synthesizeAssociation(CLASS, PROPERTY), which "synthesizes a property for a class using associated objects. This is primarily useful for adding properties to a class within a category. PROPERTY must have been declared with #property in the interface of the specified class (or a category upon it), and must be of object type."
So many of the tools in this library open (way-up) the things you can do with ObjC... from multiple inheritance... to well, your imagination is the limit.
It isn't really meaningful to do so since a protocol can't actually implement the method. A protocol is a way of declaring that you support some methods. Adding a method to this list outside the protocol means that all "conforming" classes accidentally declare the new method even though they don't implement it. If some class implemented the NSObject protocol but did not descend from NSObject, and then you added a method to the protocol, that would break the class's conformance.
You can, however, create a new protocol that includes the old one with a declaration like #protocol SpecialObject <NSObject>.
I think you may be mixing up terms here and there. Extensions, Categories, Protocols, Interfaces and Classes are all different things in Objective-C. In The Objective-C 2.0 Language Apple describes the differences very well, including the benefits and drawbacks to using categories and extensions.
If you think about it, what is a "Category" or "Extension" in the conceptual sense? It's a way of adding functionality to a Class. In Objective-C, protocols are designed to have no implementation. Therefore, how would you add or extend the implementation of something that doesn't have implementation to begin with?
if you're already writing a category, why not just add in the protocol definition in the header right after the category definition?
i.e.
#interface NSString (MyCategory)
- (BOOL) startsWith: (NSString*) prefix;
#end
#protocol MyExtendedProtocolName <NSString>
//Method declarations go here
#end
this way any class that imports the category header will also get the protocol definition, and you can add it into your class..
#interface MyClass <OriginalProtocol,MyExtendedProtocolName>
also, be careful when subclassing NSString, it's a cluster and you may not always get the behaviour you're expecting.
Adam Sharp posted a solution that worked for me.
It involves 3 steps:
Defining the methods you want to add as #optional on a protocol.
Making the objects you want to extend conform to that protocol.
Copying those methods into those objects at runtime.
Check out the link for the full details.