PDA

View Full Version : [self set] or just = ?




yaniv92648
Feb 21, 2010, 02:57 AM
Hi,
1. Suppose i have an instance variable named "tmp" Is there a difference between [self setTmp:nil] and tmp=nil?
2. besides the getter and setter thing, is there a difference between a property instance variable and a non-property instance variable?
Thanks.



robbieduncan
Feb 21, 2010, 03:47 AM
1) Yes. One is a method call and the other is just a statement. More seriously if you don't release whatever tmp was pointing to when you set it to nil then you leak memory. The setter (if correctly written or synthesised) will do this.

2) In real terms I don't think so. You can use the object.variable = newVal syntax with properties but this just calls [object setVariable:newVal] really.

yaniv92648
Feb 21, 2010, 03:58 AM
About 1, nil was just an example, the question wasn't about release, suppose i have an instance variable named "tmp", is there a functional difference between [self setTmp:tmp2] and tmp=tmp2?

robbieduncan
Feb 21, 2010, 04:00 AM
Yes: one is a method call the other isn't.

yaniv92648
Feb 21, 2010, 04:12 AM
Besides that it's exactly the same?

robbieduncan
Feb 21, 2010, 04:30 AM
Besides that it's exactly the same?

It depends on what setTmp: does. You seem to assume that it only ever releases the current pointed at object and sets the pointer to the new object. There is nothing preventing a programmer writing all sorts of actions into setTmp:

In general one object should never have direct access to the state variables on another object. So what this means is that an object can call tmp=whatever to set it's own property or instance variable but another object should never call that. Other objects should always call setTmp: as they should not make assumptions about the internal state of the other object.

If we look at a concrete example:


@interface Rectangle
{
int width;
int height;
int area;
}
-(void) setWidth:(int) newWidth;
-(void) setHeight:(int) newHeight;
-(int) area;
@end


Note that whilst I've used primitive types here this holds true for objects too.

In this case we might think that the implementation of area calculates the area when called. But this is not necessarily true and we cannot make this assumption from outside the object. It's just as possible that setting width or height (via setWidth: or setHeight:) calculates the area at that point and stores it in the ivar.

So if we assume that the implementation of Rectangle is as below:


@implementation Rectangle

-(void) setWidth:(int) newWidth
{
width = newWidth;
area = width * height;
}

-(void) setHeight:(int) newHeight
{
height = newHeight;
area = width * height;
}

-(int) area
{
return area;
}
@end


So if we wanted to create a subclass of Rectangle called Square we could make a mistake and set the width and height directly:


@interface Square : Rectangle
@end

@implementation Square
-(void) setWidth:(int) newWidth
{
width = newWidth;
height = newWidth;
}

-(void) setHeight:(int) newHeight
{
width = newWidth;
height = newWidth;
}
@end


This is wrong: a call to area will now return the wrong value. In this case calling the setters from the superclass is required to correctly keep the implementation of area. This will work:


@interface Square : Rectangle
@end

@implementation Square
-(void) setWidth:(int) newWidth
{
[super setWidth:newWidth];
[super setHeight:newWidth];
}

-(void) setHeight:(int) newHeight
{
[super setWidth:newWidth];
[super setHeight:newWidth];
}
@end


Hopefully this illustrates some of the potential issues of not using the setter methods. I would say use them as much as possible: only set the variable directly in the setVariableName: method.

Note that I've typed all this straight into the reply box. It's probably got mistakes.

firewood
Feb 21, 2010, 12:52 PM
... is there a functional difference between [self setTmp:tmp2] and tmp=tmp2?

Whether or not there is a difference depends on the implementation of the object hierarchy containing the "tmp" instance variable. If you, or somebody else, goes back and changes the definition of an object, then there might well be a huge difference, and a major opportunity for bugs. If not, and no one ever overrides or rewrites the setter for a non-object instance variable, then no there's no difference.

The OOP religious fanatics make the assumption that you will become forgetful about the current code, mindlessly reuse the code without reading it, or that your project will eventually be maintained by a large team, and the implementation will get changed, which will screw up the simple assignment, but not the setter call. You can decide on the odds of this type of error happening (they are non-zero, but usually not 100% either), and whether spending/wasting time on writing this doctrinal excellence/nonsense is a reasonable tradeoff for your sense of risk.