Reputation: 3095
I'm having a hard time understanding private instance variables through example. After reading about private instance variables, I went to Xcode and tried to verify how they work.
In the book I'm reading, it states that if you declare an instance variable in the implementation file of a superclass, the instance variable will be private and inaccessible to subclasses.
I tried proving it doing the following without any luck.
/** SuperClass interface file**/
#import <Foundation/Foundation.h>
@interface ClassA : NSObject
-(void) setX;
-(void) printX;
@end
/**SuperClass implementation file **/
#import "ClassA.h"
@implementation ClassA
{
int x;
}
-(void) setX
{
x = 100;
}
-(void) printX
{
NSLog(@" x is equal to %i", x);
}
@end
/** interface file of subclass **/
#import "ClassA.h"
@interface ClassB : ClassA
@end
/**Main file **/
#import "ClassA.h"
#import "ClassB.h"
int main(int argc, const char * argv[])
{
@autoreleasepool
{
ClassA * a;
a = [[ClassA alloc] init];
ClassB * b;
b = [[ClassB alloc] init];
[b setX];
[b printX];
}
return 0;
}
The program prints the following: x is equal to 100
isn't "x" a private instance variable and inaccessible by object "b", because "x" is declared in the implementation file of superClass "a" while "b" is a subclass?
The books says "instance variables that are to be accessed directly by a subclass must be declared in the interface section and not in the implementation section...Instance variables declared or synthesized in the implementation section are private instance variables and are not directly accessible by subclasses."
Really confused by this.
Upvotes: 1
Views: 1584
Reputation: 8090
Ivars have @protected
attribute by default, means subclasses can access them. To declare ivar as private, use @private
attribute before ivar declaration:
@interface ClassA : NSObject
{
@private
int x;
}
If you declare your ivars in @implementation
section, the only way for them to be visible to subclasses is to import .m file in your subclass, but your can't use them because they're private.
Or don't use ivars at all, since Objective-C properties now create ivars automatically. If you need a private property, you can declare it via anonymous category in .m file like this:
@interface MyClass ()
@property (nonatomic) NSInteger x;
@end
UPDATE: I think I understand what's confusing you. Public and protected ivars are inherited by subclasses and can be accessed directly as instance variables of subclass, no need to use accessor methods from a subclass.
Upvotes: 0
Reputation: 17317
The methods setX
and printX
are public and visible and thus can be called on the instance of ClassB
. Since they are public they can also be called by the ClassB
, like this.
@implementation ClassB
- (void)fig {
[self setX];
}
@end
What can't be done is for ClassB
to directly access the value x. Like this:
@implementation ClassB
- (void)foo {
NSLog(@"x is now %i", x);
}
@end
ClassB
does not have direct access to x
, but it has indirect access to x
through the superclass methods. This indirect access is an object oriented programming concept known as encapsulation.
Upvotes: 3