Brosef
Brosef

Reputation: 3095

Negation operator logic not making sense

I'm having trouble understanding with the code below. It involves a setter with an if statement that requires the origin variable to be zero (false) before executing.

The negation operator in the if statement requires origin to be zero (false) to execute, how come it executes after origin is assigned a value.

/**implementation file **/
-(void) setOrigin : (XYPoint *) pt
{
    if (! origin)
        origin = [[XYPoint alloc] init];

    origin.x = pt.x;
    origin.y = pt.y;
}


/** Main file **/
myPoint.x = 2;
myPoint.y = 3;

shape1.origin= myPoint;

myPoint.x = 2;
myPoint.y = 3;

shape1.origin= myPoint;

}

myRect.origin = myPoint;

^^The first time this method appears,the method is executed because the instance variable is zero and (! origin) is valid.

However, if I change the values of myPoint in the next line and set myRect.origin = myPoint again, the setter method shouldn't work because (! origin) is no longer true because it already contains a non zero value from the previous setting execution. Why does it still execute despite this logic? Am I wrong?

Upvotes: 1

Views: 124

Answers (2)

Kevin
Kevin

Reputation: 56059

You seem to be confused about the scope of the if statement. The if only affects the very next statement, regardless of whitespace. For example:

if(NO)
    foo();
bar();

foo is not called, but bar is; I have indented the code properly to emphasize this, but it is important to realize that indentation and even newlines have no effect on the code. I could write the above as:

if(NO)foo();bar();

and it will be precisely the same. It is for this reason that you have to watch out for empty statements; the following is a common error:

if(NO);
    foo();
bar();

Did you spot the problem? The semicolon at the end of if(NO); counts as ending the (empty) statement the if affects! That means that foo() will be executed despite its misleading indentation. Another issue I have run into is this:

if(NO)
//    foo();
bar();

Did you spot this one? bar(); is the first statement after the if, so it is not called!

Braces, regardless of their content, are a single (compound) statement, so:

if(NO) {}
if(NO) {
    foo();
}
if(NO) {
    foo();
    bar();
}

I don't think there are any surprises here: everything within the braces is not executed because the braces and all its contents are a single statement. Using braces prevents the two errors I mention and makes it clear what the programmer intended. For this reason, I suggest always using braces to make explicit what you want the if to do.

In your particular case:

if (! origin)
    origin = [[XYPoint alloc] init];

origin.x = pt.x;
origin.y = pt.y;

you could rewrite the if with braces to make it clear:

if (! origin) {
    origin = [[XYPoint alloc] init];
}

origin.x = pt.x;
origin.y = pt.y;

This means "if origin is not already an object, initialize it to a new XYPoint. If not, don't bother, we don't need or want to create a new object every time. But regardless of whether you had to create the object or not, set its x and y coordinates to the ones passed in.

Upvotes: 2

uchuugaka
uchuugaka

Reputation: 12782

That if statement only checks to see if origin exists, and if origin does not exist, it allocates and initializes origin, before setting the values to the values from the method argument.

Basically it's a convenience method. The first time you call it, the origin is created if needed, then set to the arg.

If origin exists then it just proceeds to do the setting.

Upvotes: 0

Related Questions