This short article covers Objective-C 2.0 property accessors that do not have an associated instance variable.
Objective-C 2.0 offers the ability to automatically declare and implement class properties via the @property
and @synthesize
compiler directives. For the most part, these two compiler directives, part of the Declared Properties feature, go hand in hand with each other when all you need is a quick way to expose an object’s properties, that is, the class instance variables, to functions in other classes.
In 99% of the circumstances, to access a readable and writable object property, the automatically implemented property accessor is all you need. However, in some cases, usually involving range checking, secondary functionality when the property is assigned, such as updating other properties to reflect the changes, or synthesizing property values from other sources such as a database or calculation, providing your own property accessors is a necessity. In a nutshell, property accessors do not need to be directly related to an object’s properties.
The following example program implements three Declared Properties. Two of the Declared Properties are backed by real object properties, i.e. instance variables, that record the first name and last name of an employee of a fictitious telegraph company. The third Declared Property of the object is synthesized by combining the first name and last name of the telegraph company employee to form the person’s full name.
Because the full name is created by joining two properties together, it is denoted as read-only so that we don’t have to deal with the reverse of separating a full name into first name and last name for this simple example. You can of course implement a read-write property accessor that has no associated instance variables, the property instead performing other functions besides just setting or getting the value of a class instance variable.
#import <Foundation/Foundation.h>
@interface TelegraphEmployee : NSObject
NSString * m_firstName;
NSString * m_lastName;
@property(readonly) NSString *fullName;
@property(retain, readwrite) NSString *firstName;
@property(retain, readwrite) NSString *lastName;
@end
@implementation TelegraphEmployee
@synthesize firstName = m_firstName;
@synthesize lastName = m_lastName;
- (NSString *) fullName
{
return [NSString stringWithFormat:@"%@ %@", m_firstName, m_lastName];
}
@end
int main (int argc, const char * argv[])
{
// standard Foundation housekeeping
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
// define a telegraph employee
TelegraphEmployee *employee = [TelegraphEmployee new];
employee.firstName = @"Charles";
employee.lastName = @"Bordeaux";
// output the first name and last name of the telepgrah employee
NSLog(@"Employee First Name: %@", employee.firstName);
NSLog(@"Employee Last Name: %@", employee.lastName);
// output the full name of the employee
NSLog(@"Employee Full Name: %@", employee.fullName);
// standard Foundation housekeeping
[pool drain];
return 0;
}
Employee First Name: Charles
Employee Last Name: Bordeaux
Employee Full Name: Charles Bordeaux
The program output shows that the telegraph employee’s first and last name object properties have been correctly set, and then the object property full name, which is a compound string made up of the first name object property and the last name object property is displayed. Pay attention to the property get accessor for the telegraph employee’s full name, it actually directly accesses the instance variables m_firstName and m_lastName, but it could have easily just used the property accessors to get these values too.
The ability to encapsulate data with property accessors is a powerful feature in any object oriented language, but beyond just simple encapsulation, having properties that return data synthesized from other sources, or perform sanity checking on the supplied values before assigning them, especially if the assigned statement would tie up valuable resources or perform a lengthy background operation on another thread, that might not be needed if the same value were supplied twice in a row, or was outside of a valid range, is a valuable addition to any programmer’s toolbox.