Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Protocol inheritance in 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?

like image 619
Matt McMinn Avatar asked Mar 25 '11 16:03

Matt McMinn


2 Answers

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).

like image 184
Anomie Avatar answered Oct 17 '22 04:10

Anomie


[XCode 3.2]

The compiler bug is in implementation of protocol inheritance. In the example when compiling POC there are two paths to ProductionProtocol:

  1. POC -> Production -> BaseProduction -> ProductionProtocol
  2. 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...

like image 36
CRD Avatar answered Oct 17 '22 03:10

CRD