Peter
Peter

Reputation: 13

Initializing Objective-C property in child class

Apple recommends that you access the instance variables that back your properties directly, rather than using a getter/setter, when initializing a class:

https://developer.apple.com/library/archive/documentation/Cocoa/Conceptual/ProgrammingWithObjectiveC/EncapsulatingData/EncapsulatingData.html

However, it seems that instance variables backing a property in a parent class are not accessible in the child class; why is this the case? I'm extending a class in a library (Cocos2d) where not all the instance variables are initialized in the parent class init function. For example:

---

@interface parentClass

@property (assign) int myProperty;

----

@interface childClass : parentClass

----

@implementation childClass

- (id) init {
  // this doesn't work.
  _myProperty = 0;
}

Upvotes: 1

Views: 1526

Answers (2)

LightMan
LightMan

Reputation: 3575

You can do the following in your parentClass.h:

@interface parentClass {
  @protected
  int _myProperty;
}
@property (nonatomic) int myProperty;

Then, in your childClass.m

- (instancetype)init {
    if (self=[super init]) {
        _myProperty = aValue;
    }
}

iVars are declared as protected by default, so your children can see them. There is no need to write @protected. And for your information you can also declare them as @private or @public.

But if you write the protected iVar in a private interface in your parentClass.m, this will not work and the children will not see it.

Upvotes: 0

Sebastian
Sebastian

Reputation: 7720

You can't access instance variables from your superclass in a subclass, so _variableName will also not work.

You init method will look something like this

- (instancetype)init {
    if (self=[super init]) {
        // subclass initialisation goes here
    }
}

Once [super init] returned an object, the superclass part of your object is initialised, so it should be safe to access properties using their getters and setters:

- (instancetype)init {
    if (self=[super init]) {
        self.superClassProperty = aValue;
    }
}

Have a look at "Don't message self in Objective-C init" on QualityCoding on when to use instance variables and when to call methods (e.g. property accessors). In short: Only call methods when your object is in a consistent state.

Why can't you access backing ivars?

A property declaration in a header declares a getter and setter for the property, a backing ivar is created when the property is synthesised, which happens in the implementation. (Automatic and manual synthesis doesn't make a difference). The ivar declaration is therefor only visible in the implementation. If you absolutely have to access ivars in subclasses, you have to make them public (or semi-public by putting them in a header for subclassing only).

Upvotes: 2

Related Questions