0

I declared one property in a class:

@property double x;

Then I made a subclass of that class in which I declared two more properties:

@property double a, b;

Then I made an init method in the subclass:

-(id)initWithAValue:andBValue:

And I am allowed to use:

_a;  // same for b
[self setValue a]; // same for b
self.a;  // same for b and x

Now, when I try to use the x property, I can only use [self setValue x] and I can't use _x. Why?

Rudolf Real
  • 1,948
  • 23
  • 27
SemAllush
  • 477
  • 8
  • 16
  • 2
    Because _x is not a property. _x is the ivar that backs the property. Use self.x instead. – memmons Oct 24 '14 at 16:05
  • Conceptually, subclasses aren't responsible for initializing inherited ivars -- doing so violates encapsulation. – jlehr Oct 24 '14 at 17:46

1 Answers1

6

You are able to get/set the property, you just can't directly access the instance variable/backing store behind it, which you typically don't do anyway even when they belong to the subclass.

_x is the instance variable or ivar. self.x is the property, accessed via getter/setter methods created when you use @property to declare x.

When you use @property (previously used with @synthesize, no longer required) it auto-generates the getter, setter, and backing ivar. The ivar itself, depending on where it's declared is created either as @protected or @private. Responses to this question, while a bit old, give some insight to the different visibility modifiers.

If you declare @property double x in your public .h file, it will be @protected by default, meaning that both the accessor methods and the ivar should be visible to instances of the superclass and subclasses, but not to instances of other outside classes.

If you declare that same @property in a class extension or the @implementation block in your .m (exposing only what you really need to), it's @private by default, meaning the ivar is only accessible by instances of that exact class - not subclass instances. This leaves only the getter/setter methods exposed to the subclass.

You can override these defaults if you choose, but generally it's preferable to use accessor/mutator methods & not deal directly with ivars. This is by design, since you want to control exactly how other objects, even subclass instances, can access/manipulate your variables.

Community
  • 1
  • 1
mc01
  • 3,750
  • 19
  • 24
  • You might want to edit your answer a bit. The default visibility of an ivar is `private` if declared in a class extension or `@implementation` block, but otherwise would be`protected`. Note that the default visibility can be explicitly modified by a using one of the visibility modifiers (e.g., `@package`, @`protected`, etc.). – jlehr Oct 24 '14 at 17:44
  • @jlehr Thanks - good point. Was just trying to offer a quick/simple response, but have edited for accuracy. If there's anything still amiss, please let me know. – mc01 Oct 24 '14 at 18:49
  • I think "If you declare `@property` double x in your public .h file, it will be `@protected`by default, meaning that both the accessor methods and the ivar should be visible to instances of the superclass and subclasses..." is wrong. Today, ivars of properties declared in an @interface declaration (regardless of whether its in a .h or .m) are `@private`. This makes sense because just because a property is declared (e.g. `@property BOOL myProp`) in a header, does not guarantee it is backed by an ivar called `_myProp`, much less an ivar at all. – nteissler Feb 07 '21 at 01:31