SundayMonday
SundayMonday

Reputation: 19737

Inheriting instance variables in Objective-c

In Objective-c 2.0 why do subclasses need to reference instance variables in parent classes using the self keyword?

Consider this example:

// a.h
@interface MyClass : NSObject
@property (nonatomic, retain) Object *myObject;
@end

// a.m
@implementation MyClass
@synthesize myObject;
@end


// b.h
@interface AnotherClass : MyClass
@end

// b.m
@implementation AnotherClass
- (void) someMethod {
    // error
    // Object *obj = myObject;

    // works
    // Object *obj = self.myObject;
}
@end

Upvotes: 11

Views: 8015

Answers (2)

DarkDust
DarkDust

Reputation: 92384

You haven't actually defined a variable, you only defined a property (which implicitly defines a variable that is private). And since property are just method, you need the dot syntax. Note that self.property is the same as [self property].

To fix this, specify a variable. I'll give you an example where the variable has a different name than the property. Most people chose the same name for both but I like to have them differ so I immediately see which one is meant.

// a.h
@interface MyClass : NSObject {
    // Instance variables are "protected" by default, except if you
    // use @private or @public.
    Object *myObjectVar;
}

@property (nonatomic, retain) Object *myObject;
@end

// a.m
@implementation MyClass
@synthesize myObject = myObjectVar;
@end


// b.h
@interface AnotherClass : MyClass
@end

// b.m
@implementation AnotherClass
- (void) someMethod {
    // works
    Object *obj = myObjectVar;

    // works
    obj = self.myObject;

    // the same as self.myObject
    obj = [self myObject];
}
@end

Note the difference when you assign: if you assign to your variable the object is not retained automatically. But it is retained if you use the property:

myObjectVar = someObject; // not retained, old object not released!
self.myObject = someObject; // old object released, new object retained
[self setMyObject:someObject]; // same as the line above

Edit: Mentioned that the synthesized instance variables are private by default, as noted by @Jason Coco. And @NSGod is right that normal instance variables are protected by default rather than public, fixed that.

Upvotes: 13

NSGod
NSGod

Reputation: 22948

They don't, provided you actually declare an instance variable in the superclass, rather than rely on the new runtime's ability to synthesize the instance variable (in addition to synthesizing the accessor methods). See The Objective-C Programming Language: Runtime Difference for more info on instance variable synthesis.

For example, to be able to refer to the instance variable directly, you'd need to change the following:

@interface MyClass : NSObject
@property (nonatomic, retain) Object *myObject;
@end

to:

@interface MyClass : NSObject {
// there is an implied @protected directive here
    Object *myObject;
}

@property (nonatomic, retain) Object *myObject;

@end

By default, instance variables are @protected, meaning the class and any subclasses can access the instance variables directly. @protected ivars differ from @public ivars in that you can't access them using ->. @private ivars can only be accessed by the class that declares them. See The Objective-C Programming Language: The Scope of Instance Variables for more info.

Upvotes: 8

Related Questions