Reputation: 1428
I often have a hard time deciding if certain data should be exposed through a property or a method. You can say "use properties for object state", but that's not very satisfying. Take this example for instance:
- (NSString *)stringOne
{
return _stringOne;
}
- (NSString *)stringTwo
{
return _stringTwo;
}
- (NSString *)mainString
{
return [_stringOne length] > 0 ? _stringOne : _stringTwo;
}
It's clear that stringOne
and stringTwo
should be properties because they are clearly object state. It's not clear, however, if mainString
should be a property. To the end user mainString
acts like state. To your object, mainString
is not state.
This example is contrived but hopefully you get the idea. Yes, properties are nothing more than a convenient way to create getters and setters but they also communicate something to the user. Does anyone have decent guidelines for deciding when to use a property vs a method.
Upvotes: 7
Views: 2540
Reputation: 6092
Another consideration to take into account : do you want to store the value of the property ? (via NSCoding or in Core Data for example) I guess you NEED to create properties for things you need to "save" (in "encodeWithCoder" for instance. Deciding what you want to put in encodeWithCoder could help you decide which way you want to define things).
For things you don't need to save and can recalculate easily, you have the choice between a method and a readonly property (which is equivalent under the hood : a readonly property only creates a getter accessor method, and does not have an instance variable to back it). So that's more a question of style.
Speaking of style, if you use dot notation for properties only (as I do), you'd maybe wonder : - do I want to access the full name as foo.fullName, and not make a difference with other properties like foo.firstName and foo.lastName ? - or do you want to make a difference by accessing the full name with [foo fullName], showing to the world that this is calculated ?
I created an app for following stock quotes, and the model was inspired from an example in the Big Nerd Ranch book about Objective C (good read, by the way). Here is how properties and methods are defined :
// properties
@property (nonatomic, copy) NSString *name;
@property (nonatomic, copy) NSString *symbol;
@property (nonatomic, copy) NSString *currency;
@property (nonatomic, copy) NSString *market;
@property (nonatomic) int numberOfShares;
@property (nonatomic) double purchaseSharePrice;
@property (nonatomic) double currentSharePrice;
// Stock Calculation methods
- (double)costInLocalCurrency; // purchaseSharePrice * numberOfShares
- (double)valueInLocalCurrency; // currentSharePrice * numberOfShares
- (double)gainOrLossInLocalCurrency // valueInLocalCurrency - costInLocalCurrency
You can see that they are clearly distinguished. The BNR does not use dot notation at all in their book, so it would all look the same : [foo currentSharePrice] or [foo valueInLocalCurrency], but as I use dot notation for properties, I would make a difference in style between foo.currentSharePrice and [foo valueInLocalCurrency].
Hope this is helpful.
Upvotes: 1
Reputation: 64022
Hiding the split between "true" state (string1
and string2
in your example) and "dynamic" state (mainString
) is, I would say, exactly what properties are for.
The canonical example would probably be an object that represents a person, with given and family names as "state". A third piece of state, "full name" can be presented from those two pieces, but clients have absolutely no reason to know whether the full name is constructed on demand, or is created and stored when both of its pieces are set. It simply doesn't matter.
Properties are an interface -- what bits of data does this class provide to its clients (and what can the clients configure about the class)? The implementation of each property is encapsulated and does not affect its status as a property.
In ObjC, of course, we use methods to access properties. Other methods, however, represent actions that an object can take, possibly being passed some piece of data to operate on.
Upvotes: 5
Reputation:
By design, you should always respect the end user - if you think it's object state for the user of your class (which it apparently is), then go ahead and make a property out of it.
Upvotes: 0