Brosef
Brosef

Reputation: 3095

Understanding private instance variable

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

Answers (2)

Kyr Dunenkoff
Kyr Dunenkoff

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

ThomasW
ThomasW

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

Related Questions