I have the following code:
// ClassA.h
@interface ClassA : NSObject
@property (nonatomic, retain, readonly) id my_property;
@end
// ClassA.m
@implementation ClassA
@synthesize my_property;
- (id)init {
if (self = [super init]) {
self->my_property = [NSNumber numberWithInt:1];
}
return self;
}
- (void)debug {
NSLog(@"%@", self->my_property);
}
@end
// ClassB.h
#import "ClassA.h"
@interface ClassB : ClassA
@end
// ClassB.m
#import "ClassB.h"
@implementation ClassB
@synthesize my_property;
- (id)init {
if (self = [super init]) {
self->my_property = [NSNumber numberWithInt:2];
}
return self;
}
@end
I call the above code like so:
ClassB *b = [[ClassB alloc] init];
[b debug];
The output is 1
. If I change the -[Class A debug]
method to use self.my_property
, the output is 2
.
My (limited) understanding is that with the "modern" Objective-C runtime, class ivars are generated dynamically. Can subclasses of classes with these dynamically-generated ivars access said instance variables? If I do not include the @synthesize my_property
line in ClassB.m, the compiler gives me the error:
error: 'struct ClassB' has no member named 'my_property'
However, if I change the -[ClassB init]
method to use property notation rather than ivar notation, it will recognise the inherited property, albeit not let me write to it on account of it being read-only. How can I write to it while maintaining its read-only state to consumers of my API?
Clarification: A couple of answers have pointed out that I can use vanilla ivars. That is indeed correct, but then the public-facing @interface
reveals implementation details that are best kept private. As in this post on SO:
I prefer my public-facing interfaces to be as minimal and clean as possible, only revealing aspects of my class that are pertinent.