Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <blockquote> <p>This would have made the getter and setter for numberOfBackSeatPassengers available only within "Car.m"</p> </blockquote> <p>Not true. Those methods would still exist on every instance of <code>Car</code> and every instance of every object that extends <code>Car</code>, whether or not you declare them in your header file. The compiler wouldn't treat them as publicly visible and would complain if you tried to call them directly, but you'd still be able to call your getter and setter on any subclass of <code>Car</code> simply by using <code>performSelector:</code>. </p> <p>In any case, if you have a <code>@property</code> there's no point is using <code>@private</code> on the ivar that backs it (and there's also no point in having an explicit ivar backing it, one will be created automatically for you when you use <code>@synthesize</code>; but that's a separate topic). I'd suggest that if <code>SportsCar</code> is meant to extend <code>Car</code> and never allow any backseat passengers to be recorded that the 'standard' way to do that would be to simply override the getter/setter methods in <code>SportsCar</code> to either always set/return 0 or to raise some error if an attempt is made to set a nonzero value. </p> <p>Another option, since this property does not apply to all <code>Car</code> instances is to take it out of the base class entirely. You could, for example, have <code>Car</code>, and then derived from that have <code>TwoDoorCar</code> and <code>FourDoorCar</code>, and then have <code>SportsCar</code> be derived from <code>TwoDoorCar</code>. In this case you could declare <code>numberOfBackSeatPassengers</code> as a public property of <code>FourDoorCar</code>, as every four-door car should be able to accommodate passengers in the back seat.</p> <p>To get back to the original question being asked, using <code>@private</code> on an ivar affects only the visibility of that ivar. It does not affect methods which make use of the ivar. So a subclass of <code>Car</code> will not be able to see the <code>numberOfBackSeatPassengers</code> ivar itself. But since you've created a public getter/setter for it, the subclass will of course be able to see those, and use them to modify the value of the ivar. </p> <p><strong>Edit</strong></p> <p>To briefly answer the updated question(s):</p> <ol> <li><p>Yes, you can use <a href="http://developer.apple.com/library/ios/#documentation/Cocoa/Reference/Foundation/Classes/NSInvocation_Class/Reference/Reference.html" rel="nofollow noreferrer">NSInvocation</a> to dynamically invoke a method that requires primitive parameters. Or you can use the approach discussed here, which is even more straightforward: <a href="https://stackoverflow.com/questions/2650190/objective-c-and-use-of-sel-imp">Objective-C and use of SEL/IMP</a>. Or you can use a <code>NSNumber</code> instead of an <code>int</code> and then use <code>performSelector:withObject:</code>.</p></li> <li><p>I'm not sure what you're saying <code>@private</code> should be doing in this case. What is it that you think using <code>@private</code> should do?</p></li> <li><p>I think this has less to do with syntax and more to do with principles of object-oriented design. If some cars do not have a back seat, then it is not really good object-oriented design to give the <code>Car</code> superclass a <code>numberOfBackseatPassengers</code> property. Doing that gives the object a field that does not actually apply to every instance of the object type. And when you start doing that you run into exactly the sort of problems you describe in your example. The purpose of a superclass is to contain functionality that is common to all of its derived types. If it has functionality that is common only to <em>some</em> of its derived types, then that is usually a design problem. In any case, it has nothing to do with Objective-C syntax or semantics.</p></li> </ol> <p>As for what <code>@private</code> gets you, how about simplified organization of your class, for one thing? Yes you can declare an ivar in your implementation file to accomplish a similar effect, but is that really as convenient as having all the ivars declared in the header? On a reasonably complex project, will other developers be able to follow your code as easily if only <em>some</em> ivars are declared in the header and the rest are in the implementation file? </p> <p>Without <code>@private</code>/<code>@protected</code> <em>every</em> ivar declared in a header would be public, which is definitely not good in an object-oriented environment for all the reasons Jonathan pointed out. So these access modifiers probably exist, first and foremost, to solve this issue. </p> <p>As for use-cases, properties with getters/setters are probably not the best example. The purpose of getters/setters is virtually always to provide a public interface for modifying/querying the property value, and as noted in Objective-C it's not necessary to explicitly declare an ivar, in any scope, to back a synthesized property. </p> <p>A better example may be <code>IBOutlet</code>'s. You want these declared in your header so that XCode/Interface Builder can find them, but you don't want them exposed outside of your class implementation or (typically) even to subclasses of your class. So you would declare them in your header, and you generally would not add any getter/setter methods for these ivars.</p> <p><strong>Edit 2</strong></p> <p>For a specific example of where <code>@private</code> makes sense, what about something like:</p> <pre><code>@interface Car : NSObject { @private DataRecorder* blackBoxRecorder; } @property (nonatomic, strong) NSString *make, *model; @end </code></pre> <p>We know that proposed regulations may require all cars on the road to include a built-in black-box/data recorder. So every <code>Car</code> must have one, and no subclass of <code>Car</code> should be able to tamper with <code>blackBoxRecorder</code>.</p> <p>In this case having a setter method defined would not make sense. You might provide a public getter, or instead you might provide a public wrapper API around the <code>DataRecorder</code> that subclasses could use to log data. Something like <code>-(void) logEventWithName:(NSString*)name andValue:(NSNumber*)value;</code>. So subclasses can use the <code>DataRecorder</code> through the API, but they can't mess with the backing ivar itself to disable or modify the behavior of the mandated black-box/data recorder. </p> <p>But in any case, yes, I'm in general agreement with your analysis. Having <code>@private</code> mostly impacts readability/maintainability of code. It needs to exist for Objective-C to be successful as an object-oriented programming language (if all ivars were public by default and there was no way to modify that, the language would be a complete mess), but what it does from a purely <em>functional</em> standpoint is not much. It's more of a logical/organizational tool. It assists with <a href="http://en.wikipedia.org/wiki/Information_hiding" rel="nofollow noreferrer">data hiding</a> and allows you to keep all of your ivars in your header file(s), and that's about it.</p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
    3. VO
      singulars
      1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload