Synthesized property of a protocol not seeing superclass' ivar
I have a situation where my subclass is not seeing the superclass' instance variable x
. The ivar is obviously @protected
by default, so why do I get a compiler error "x undeclared"?
- (CGSize)hitSize
{
// Compiler error
return size;
}
EDIT: hitSize is a property of a protocol my subclass is confo开发者_运维百科rming to. The problem was that I had hitSize @synthesize
d, which was the culprit. The question then is why can't the synthesized getter see the ivar?
EDIT: Now that I found out the problem, I edited the question to ask why this is an error.
Joanna's answers are both correct (though ivar synthesis doesn't kick in on 32 bit Mac OS X).
The reason, though, is because allowing a subclass to synthesize access to a superclass's internal state would quite explicitly break encapsulation. The decision was made to explicitly not allow that particular pattern in all cases, even within a single framework.
If a superclass provides storage for something, it should provide the access control and encapsulate the management of said memory. If a subclass needs to customize access, do so with care by overriding the getter/setter [and, preferably, calling the super to actually get/set the value].
You can also use the explicit getter/setter attributes to access, even the @private ivars of the base class:
@interface Base : NSObject { @protected int intVar; } @end @interface Derived : Base { } @property (assign, getter = intVar, setter = intVar) int aVar; @end
Synthesized properties not only synthesize the getters and setters, they also synthesize the ivar if one is not declared.
You need to write explicit accessors in the subclass and access the@protected ivar via the self->myIvar syntax.
Thanks bbum, for elaborating on my replies.
With regard to your second reply, you are, of course, right and, in that case, you can "do things right", using a class extension to hide the property on the base class, like this:
// Example.h @interface Base : NSObject { @private int intVar; } @end @interface Derived : Base { } @property (assign) int aVar; @end
// Example.m @interface Base () @property (assign) int intVar; @end @implementation Base @synthesize intVar; @end; @implementation Derived - (int) aVar { return self.intVar; } - (void) setAVar:(int)value { self.intVar = value; } @end
精彩评论