Protocol inheritance in Objective C - objective-c

I've got a project which has in it a protocol, a class implementing that protocol, and a subclass of the implementation class. This is our production application.
#protocol ProductionProtocol<NSObject>
#property (nonatomic, retain) NSString *role;
#end
#interface BaseProduction : NSObject<ProductionProtocol>
NSString *role;
#end
#implementation BaseProduction
#synthesize role;
#end
#interface Production : BaseProduction
#end
#implementation Production
#end
I've also got a proof of concept (POC) application, which is implemented as a separate project that includes the production application. In the POC application, I have a protocol that extends the production protocol, and a class that extends the production class.
#protocol POCProtocol<ProductionProtocol>
-(void)cancel;
#end
#interface POC : Production<POCProtocol>
#end
#implementation POC
-(void)cancel{...}
#end
Notice that in the ProductionProtocol, I've got a role NSString which is declared, and implemented in the BaseProduction interface/class. in the POC, I've got a method 'cancel' which is declared in the protocol, but not in the interface/class.
So here's my question: with my class structure set up like this, I get this warning:
Property 'role' requires method '-role' to be defined - use #synthesize, #dynamic or provide a method implementation
I don't understand why I'm getting this warning. Since the synthesized properties are in the base class, they should be available to the POC class - and a quick test seems to confirm that they are. So what am I doing wrong here?

There is no official language definition for Objective-C, but according to Apple:
When a class adopts a protocol, it must implement the required methods the protocol declares, as mentioned earlier. In addition, it must conform to any protocols the adopted protocol incorporates. If an incorporated protocol incorporates still other protocols, the class must also conform to them. A class can conform to an incorporated protocol using either of these techniques:
Implementing the methods the protocol declares
Inheriting from a class that adopts the protocol and implements the methods
However, reports are that GCC doesn't recognize that the property is in an incorporated protocol and is implemented in a superclass. You could change your compiler to Clang, which is reported to handle this in the specified manner, or you could just use #dynamic to tell the compiler that an implementation of the property will be provided at run time (in this case, by inheritance from the superclass).

[XCode 3.2]
The compiler bug is in implementation of protocol inheritance. In the example when compiling POC there are two paths to ProductionProtocol:
POC -> Production -> BaseProduction -> ProductionProtocol
POC -> POCProtocol -> ProductionProtocol
This confuses GCC 4.2, it doesn't confuse Clang (LLVM 1.6, XCode 3.2).
If you change POCProtocol to:
#protocol POCProtocol//<ProductionProtocol>
the error will go away.
You could just comment out the protocol-to-protocol inheritance and leave a TODO to remove when the compiler is fixed.
Looks like a classic compiler writer bug to me, or maybe someone confused with .NET semantics (where you can re-implement interfaces (protocols in Obj-C) along the inheritance chain).
#danyowdee suggests you file a bug report, though as it is not in Clang (I didn't fire up my mothballed XCode 4 to test its compilers) I suspect this is unlikely to be a high priority to get fixed...

Related

What type of class definition is this: ClassName<Variable> : parent

What dose ViewControllerClass means here?
As far as I know this is not protocol, delegate or extension. Any one can explain how dose this work?
.h file:
#interface BaseViewControllerTest <ViewControllerClass> : XCTestCase
#property ViewControllerClass viewController;
- (void)setUpTestWithStroyboardName:(NSString *)viewControllerName;
.m file:
#implementation BaseViewControllerTest
- (void)setUpTestWithStroyboardName:(NSString *)viewControllerName {}
Used like this:
#import "BaseViewControllerTest.h"
#interface CTSelectChildAccountViewControllerTests : BaseViewControllerTest <CTSelectChildAccountViewController *>
#end
Starting with Xcode 7 Objective-C supports generics:
Objective-C has been updated to enable it and Swift to work together more easily and efficiently. The new Objective-C language features include:
Generics. Allow you to specify type information for collection classes such as NSArray, NSSet, and NSDictionary. The type information improves Swift access when you bridge from Objective-C and simplifies the code you have to write.
CTSelectChildAccountViewController is a ViewController. Dose that mean ViewControllerClass is defined as UIViewController?
The asterisk from the instantiation is relevant too, so ViewControllerClass viewController is interpreted as CTSelectChildAccountViewController* viewController.
What is the benefit except Swift?
Objective C compiler has more type information now, so it can perform better checks on the methods that you call. For instance, you can annotate Cocoa collections with the type that goes into them, e.g. NSArray<NSString*> *array, and have the compiler spot places where you insert a wrong type by accident.
And how is it useful with Swift?
Swift has built-in support for generics. Adding lightweight generics to your Objective-C API makes it easier to interface with Swift, because your API gets translated more precisely. For instance, translating your example from Swift would keep its generic nature, instead of replacing generic type parameter ViewControllerClass with its base type.

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.

Category on NSObject implementing protocol causes Unimplemented Method warnings

If I define a subprotocol of the NSObject protocol with extra methods, then define and implement a category on NSObject that declares conformance to that protocol, I get warnings on compilation. The compiler complains that my NSObject category doesn't implement all the methods declared in the NSObject protocol.
I don't understand why this is the case. The NSObject class (in <Foundation/NSObject.h> declares that it conforms to the NSObject protocol (and, redundantly, that it implements these methods) - shouldn't that suffice?
What's the cause of the problem here?
Sample code - if you compile this, you'll see warnings on the NSObject (CategoryToImplementMyProtocol) implementation:
#protocol MyProtocol <NSObject>
- (void)myMethod;
#end
#interface NSObject (CategoryToImplementMyProtocol) <MyProtocol>
#end
#implementation NSObject (CategoryToImplementMyProtocol)
- (void)myMethod
{
NSLog("A la peanut butter sandwiches!");
}
#end
I found a couple of questions addressing this, but all the answers were of the "do this workaround!" variety, not that "this is the cause of the problem" variety (or just plain wrong, despite being accepted...). I know I can work around this. I'd really like to understand why it fails.
The problem is that you are declaring adoption of the <NSObject> protocol again. The way protocols work in Objective-C (for better or for worse) is that a category implementation must implement all of the protocols that are specified in its interface.
In addition, protocol conformance is nominal rather than structural in Objective-C. That is to say, for a class to respond to the correct methods is not enough for it to have adopted that protocol.
Edit: Seems the example code has been changed, and I guess my answer isn't really relevant anymore.

Can a category simultaneously implement a protocol?

If a category I'm creating for a class adds methods that also fulfill the contract set out by a protocol, I'd like to flag that category class as implementing the protocol, and thereby indicate to the Obj-C pre-processor that the class effectively implements the protocol as well.
Example delegate (for clarity, thanks Ole!):
#protocol SomeDelegate <NSObject>
- (void)someDelegateMessage;
#end
Example category:
#interface NSObject (SomeCategory) <SomeDelegate>
- (void)someDelegateMessage;
#end
And with an otherwise typical implementation
#implement NSObject (SomeCategory)
- (void)someDelegateMessage {}
#end
When I actually try this, I get a warning for each NSObject method:
warning: incomplete implementation of category 'SomeCategory'
warning: method definition for '-description' not found
...
warning: method definition for '-isEqual:' not found
warning: category 'SomeCategory' does not fully implement the 'NSObject' protocol
Works fine if I remove <SomeDelegate> from the declaration, but of course NSObject isn't recognized as a SomeDelegate
A workaround is to declare the protocol on a category with no implementation, and implement the method in a different category, e.g.:
#interface NSObject (SomeCategory) <SomeDelegate>
- (void)someDelegateMessage;
#end
#implementation NSObject (SomeCategory_Impl)
- (void)someDelegateMessage {}
#end
If you do this, NSObject will be considered to conform to <SomeDelegate> at compile time, and runtime checks for someDelegateMessage will succeed. However, conformsToProtocol: runtime checks will fail.
Of course, you should file a bug requesting that methods declared on the core class don’t generate warnings.
Any chance your protocol declaration includes the NSObject protocol? Like this:
#protocol SomeDelegate <NSObject>
...
That's where the warnings are coming from because now your category does not implement the full protocol. In the test code I just typed up, removing NSObject from the protocol removes the compiler warnings.
If you want the compiler to shut up about sending <NSObject> messages (and its important that you remember that thats the protocol name, not the class name) then just use 'id' variables, not 'id' since thats you explicitly telling the compiler "This is an object which only implements the SomeDelegate protocol".
Alternately, use NSObject as your variable type instead.

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.