I have a doubt regarding property redeclaration
Overview:
- class “A” is the parent class with a readonly property int n1;
- class “B” is the subclass, which redeclares the property as read write
- using the setter of class “B” the property value is set as 20
- when i print the value using the getter and the instance variable I seem to get different values
Points to note: – Memory management = ARC (Automatic Reference Counting)
Question:
- When I print the values of self.n1 and _n1 why do I get different values ?
- My expected behavior and actual behavior don’t match why (Pls scroll down to see the actual vs expected) ?
Code: (in separate files)
A.h
#import<Foundation/Foundation.h>
@interface A : NSObject
@property (readonly) int n1;
- (void) display;
@end
A.m
#import "A.h"
@implementation A
@synthesize n1 = _n1;
- (void) display
{
printf("_n1 = %i\n", _n1); //I expected _n1 and self.n1 to display the same value
printf("self.n1 = %i\n\n", self.n1); //but they seem to display different values
}
@end
B.h
#import"A.h"
@interface B : A
@property (readwrite) int n1;
@end
B.m
#import"B.h"
@implementation B
@synthesize n1 = _n1;
@end
test.m
#import"B.h"
int main()
{
system("clear");
B* b1 = [[B alloc] init];
b1.n1 = 20;
[b1 display]; //Doubt - my expected behavior is different from actual behavior
return(0);
}
Expected Behavior:
_n1 = 20
self.n1 = 20
Actual Behavior:
_n1 = 0
self.n1 = 20
There are two ways of going about this. In neither case do you call
@synthesizein the subclass.I’m surprised that compiles for you. I would expect an error like “Property ‘n1’ attempting to use ivar ‘_n1’ declared in superclass ‘A'”.In any case it’s definitely not something you can really do, which is why you’re seeing strange behavior. (I remembered why you aren’t seeing this error; it’s because of the separate compile units. You’re just winding up with different ivars.)First, you need to understand
@dyanmic. This is a way of telling the compiler “yes, I know you don’t see an implementation for the required method here; I promise it’ll be there at runtime.” In the subclass, you will use@dynamicto let the compiler know that it’s ok to inheritn1.Now, you need to provide the
setN1:method. IMO, subclasses shouldn’t go messing with their superclass’s ivars, so I approve of the fact that synthesized ivars are marked@private. In a second, I’ll tell you how to undo that, but for now let’s deal with my preferred solution:setN1:as a private method inA.B.A.h
A.m
B.h
B.m
Now, some people think it’s fine for subclasses to mess with their superclass’s ivars. Those people are wrong (ok, IMHO…) but it is possible in ObjC. You just need to declare the ivar
@protected. This is the default when you declare ivars directly in the@interface(one of many reasons you shouldn’t do this anymore). It would look like this:A.h
A.m — remove the extra class extension that makes n1 writable in the superclass.
B.h — no change
B.m