(Objective C) what is the advantage of doing @synthesize myvar = _myvar (if any)? [duplicate]

Possible Duplicate:
How does an underscore in front of a variable in a cocoa objective-c class work?

It is not fully clear to me (other than for readability of the code), why you wanna create an internal variable with an underscore prefix when you create the property.

Since everything is handled internally, why bother to do so, since we do not add any code to the getter and setter?

And even if i gotta add some code to the getter or setter, i do not see why i cannot just do the check on myvar instead than having to check _myvar and then assign it to myvar.

Can anyone give me some explanation, other than "do it because that's what everyone does ?" I would like to understand the whole reason behind this practice (that seems to be pretty common even if there is no custom code for the getter and setter).

Thanks!


Solution 1:

I've wondered this many times myself. Interested in other people's answer, but one reason I've found is that it forces you to notice if you're accessing the ivar directly when you should be using the getter/setter.

self.myvar = @"blah"; and _myvar = @"blah";

vs

self.myvar = @"blah"; and myvar = @"blah";

It's easy to leave the self. out by accident... it's a lot harder to put the _ in by accident.

Solution 2:

An Objective-C property usually has a backing instance variable (I guess you know the difference between a property and an instance variable).

The property may have a different name than the instance variable.

For instance, you may have an instance variable named x, with a property named y.

You can synthesize the y property to the x variable using:

@synthesize y = x;

Now about the underscore.

It's a common practice to use an underscore prefix for instance variables, to prevent naming collisions, or compiler warnings (shadowed variable), when having for instance a method argument with the same name as an instance variable.

The underscore prefix also makes clear that you are referring to an instance variable.

By using the underscore prefix for instance variables, you're free to use the name without the underscore in method's arguments, stack variables, etc.

But when using a property, you usually don't want the user to write an underscore.

So you usually have an x property for an _x instance variable.

This is why you write:

@synthesize x = _x;

Let's take an example:

@interface Test: NSObject
{
    int x;
}

@property( readonly ) int x;

@end

This is quite common... But now imagine this in the implementation:

- ( id )initWithX: ( int )x
{}

We have are a naming collision.

Inside our method, x will refer to the method's argument. And there is no pretty way to access the x instance variable.

Depending on your compiler's warning flags, this may also generate a warning (-Wshadow).

If you use an underscore prefix for your instance variable, everything is just simple:

- ( id )initWithX: ( int )x
{
    if( ( self = [ super init ] ) )
    {
        _x = x;
    }

    return self;
}

No conflict, no naming collision, improved reading... Just a nice way...

Solution 3:

When using a property of self, it's easy to forget the "self":

[self.field doSomething]; // what you probably want
[self setField:someObject]; // also kosher
self.field = someObject; // ditto, although not my style

vs.

[field doSomething] // might work.. but will bite you eventually
field = someObject; // almost certainly wrong anywhere outside a custom setter

If the property and the ivar are named identically, the latter cases will compile without complaint and appear to work... until they don't, and you get a weird hard-to-reproduce edge case bug.

If the ivar has a slightly different name, say with a trailing _ appended, the compiler will stop you and make you explicitly decide: do I want to refer to the property here, or the ivar directly?

(All that said, I am lazy and often do @synthesize field;, and replace it later with @synthesize field = field_; when I actually need the distinct ivar, say when it's custom-setter-writing time.)