Errata on "Learn Objective-C on the Mac" book or bad memory understanding?
In the book "Learn Objective-C on the Mac' you can find the following code which I think is an errata:
"Here's another attempt at writing setEngine:
- (void) setEngine: (Engine *) newEngine
{
[engine release];
engine = [newEngine retain];
}
... ponde开发者_Python百科r this case:
Engine *engine = [Engine new]; // count: 1
Car *car1 = [Car new];
Car *car2 = [Car new];
[car1 setEngine: engine]; // count: 2
[engine release]; // count 1
[car2 setEngine: [car1 engine]]; //Ops...
Why is this a problem? Here's what's happening. [car engine] returns a pointer to engine which has a retain count of 1. The first line of setEngine is [engine release], which makes the retain count 0, an the object gets deallocated...."
However, after reading this paragraph on page 166. I wonder what the internal engine reference in car2 has to do with engine in car1. They are two different references and by te time "[car2 setEngine: [car1 engine]]" is invoke, the engine in car2 hasn't been initialized and keeps no relation to the retained engine the author talks about. So "[engine release]" won't decrease te counter to 0 of car1 engine. See my point? Is it an errata or am I terrible wrong?
((I would like to discuss this particular code, not the right way of implementing a setter))
What class is setEngine: in? I'm assuming it's in Car. And that Car has an instance variable of type Engine* called engine. Which is NOT the same Engine* pointer as in the second code fragment (which should be a controller class with it's own instance variables).
First, engine IS initialized. [Engine new]
is the same (for all practical purposes) as [[Engine alloc] init]
.
So you've got two Car objects, and 1 Engine object. You set the engine instance variable in car1 to point to the engine object. Then release the original pointer. Fine. Then you assign it to car2 as well. If car2 had a different engine, it gets released and the new one assigned. If it didn't have an engine assigned, the release message gets sent to nil (which is fine), and it gets assigned as well.
It's all fine.
PS - while Objective-C has the new
construct, it's generally a bad idea to use it because it obscures the two-stage creation pattern that is the norm for Apple frameworks. Use alloc & init.
The setter isn't right. It might be:
- (void) setEngine: (Engine *) newEngine
{
if(newEngine != engine)
{
[engine release];
engine = [newEngine retain];
}
}
精彩评论