10
votes

Let's say that I have the following protocols defined:

// basic protocol for an User Interface object:

@protocol UIObjectProtocol <NSObject>
@property (assign) BOOL touchable;
@end

// basic protocol for an User Interface object that is held by a holder object:

@protocol UIHeldObjectProtocol <UIObjectProtocol>
@property (readonly) id holder;
@end

And the following class hierarchy:

// base class for an User Interface object, which synthesizes the touchable property

@interface UIObject : NSObject <UIObjectProtocol> {
   BOOL _touchable;
}
@end

@implementation UIObject
@synthesize touchable=_touchable;
@end

At this point, everything is OK. Then I create a UIObject subclass named UIPlayingCard. Inherently, UIPlayingCard conforms to the UIObjectProtocol since it's superclass does it too.

Now suppose I want UIPlayingCard to conform to UIHeldObjectProtocol, so I do the following:

@interface UIPlayingCard : UIObject <UIHeldObjectProtocol> {
}
@end

@implementation UIPlayingCard
-(id)holder { return Nil; }
@end

Note that the UIPlayingCard conforms to UIHeldObjectProtocol, which transitively conforms to UIObjectProtocol. However I'm getting compiler warnings in the UIPlayingCard such that:

warning: property 'touchable' requires method '-touchable' to be defined - use @synthesize, @dynamic or provide a method implementation

which means that the UIPlayingCard superclass conformance to the UIObjectProtocol wasn't inherited (maybe because the @synthesize directive was declared in the UIObject implementation scope).

Am I obligated to re-declare the @synthesize directive in the UIPlayingCard implementation ?

@implementation UIPlayingCard
@synthesize touchable=_touchable; // _touchable now must be a protected attribute
-(id)holder { return Nil; }
@end

Or there's another way to get rid of the compiler warning? Would it be the result of bad design?

Thanks in advance,

4
This has nothing to do with your problem, but it's generally not the best idea to use "Apple's" prefixes for your own classes/protocols/constants/whatevers: You never know what big fruit will include in the next release... - danyowdee
I agree with you danyowdee, in fact I'm not using the 'UI' prefix in my application and I do follow all these good practices listed by you. I just suppressed the real prefix (the company prefix, for instance) here in the post since it has no relation with the problem. - Eduardo Coelho

4 Answers

3
votes

You comment that _touchable would then have to be protected, but you did not include an @private compiler directive, so _touchable is already protected.

Clang does not seem to give this warning in this case, so the most straightforward solution:

  • Change your compiler from GCC to Clang.

This will have plenty of side-benefits, as well, including much more intelligible error and warning messages.

It is a bug that GCC complains about this. The implementation is in fact inherited, as you can verify with a simple main function exercising UIPlayingCard's touchable property. So, your second solution:

  • Ignore the warning as bogus. If none of your tests are failing, what do you care, anyway?
2
votes

I'll just throw in one other way to silence the warning: use @dynamic, and the compiler will assume that the implementation will be provided in some other way than in a declaration in the class's implementation (in this case, it's provided by the superclass).

2
votes

Am I obligated to re-declare the @synthesize directive in the UIPlayingCard implementation

Although I don't see from your example, why you are doing what you are doing:

No, you don't need to re-implement methods that are already implemented in your parent class.

If the compiler warns about these methods not being present, then that is a bug:
As The Objective C Programming Language states...

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 by either:

  • Implementing the methods the protocol declares, or
  • Inheriting from a class that adopts the protocol and implements the methods.
0
votes

A Protocol is like a contract. What you are saying is that UIPlayingCard must implement holder and touchable.

When the compiler compiles UIPlaying card, it doesn't see anywhere that @property (nonatomic) BOOL touchable; is defined.

you can't add synthesize to playingCard since playingCard doesn't have the touchable ivar.

Change:

@protocol UIHeldObjectProtocol <UIObjectProtocol>

to

@protocol UIHeldObjectProtocol <NSObject>

Since UIPlayingCard inherits from UIObject, the protocols don't need to inherit from each other.