Objective-C - Data Encapsulation, Synthesized Accessors and Dot Notation
Previous | Table of Contents | Next |
Writing Objective-C Class Methods | Objective-C Inheritance |
Purchase the full edition of this Objective-C book in Print ($14.99) or eBook ($12.99) format Objective-C 2.0 Essentials Print and eBook (ePub/PDF/Kindle) editions contain 31 chapters. |
In the preceding chapter entitled An Overview of Objective-C Object Oriented Programming we looked at the basics of creating and working with objects in Objective-C. In this chapter we will look more closely at accessing data encapsulated in classes through the use of synthesized accessor methods and dot notation.
Data Encapsulation
In the previous chapter we mentioned briefly the concept of data encapsulation whereby data is contained within objects and is not accessible by any means other than via methods defined on the class. In our BankAccount class example we defined two instance variables and then wrote some methods to get, set and display those values. In this chapter we will look at some alternate programming techniques to access the data encapsulated in a class.
Synthesized Accessor Methods
Accessor methods (also referred to as getters and setters) are methods belonging to a class that allow the programmer to get and set the values of instance variables contained within that class. In our BankAccount example covered in the previous chapter we wrote accessor methods to get and set the bank account number and bank balance variables. As you can probably imagine, having to write these methods for large numbers of complex classes will ultimately prove to be time consuming. Fortunately, Objective-C provides a mechanism that automates the creation of accessor methods. These are called synthesized accessor methods and are implemented through the use of the @property and @synthesize directives. The following code demonstrates a modified version of our BankAcount class @interface definition with the two getters and setters we original wrote removed and replaced by @property directives:
#import <Foundation/Foundation.h> @interface BankAccount: NSObject { double accountBalance; long accountNumber; } @property double accountBalance; @property long accountNumber; -(void) displayAccountInfo; @end
Note that because the two properties are of different data types (double and long) it was necessary to declare them on separate @property lines. Had they been of the same data type we could have placed them on the same line, separated by commas:
@property int x, y;
Having declared the properties, the next step is to declare that synthesized accessor methods are required. This is performed in the @implementation section of the class definition:
@implementation BankAccount @synthesize accountBalance, accountNumber; -(void) displayAccountInfo { NSLog (@"Account Number %ld has a balance of %f", accountNumber, accountBalance); } @end
Note that regardless of data types of the properties involved, the variable names may be placed on a single @synthesize line as illustrated above.
Having created the accessors, the question that now arises is what these methods are named. In assigning a name to a synthesized accessor method, Objective-C takes the name of the instance variable (for example accountBalance), capitalizes the first letter (AccountBalance) and then pre-fixes it with set (setAccountBalance). For example:
BankAccount *account1; account1 = [BankAccount alloc]; account1 = [account1 init]; [account1 setAccountBalance: 1500.53]; [account1 setAccountNumber: 34543212];
Direct Access to Encapsulated Data
Data encapsulation encourages the use of methods to get and set the values of instance variables in a class. Now is probably the time to point out this is a guideline rather than a rule. In fact, it is quite common for developers to want to directly access an instance variable without having to go through an accessor method. The Objective-C syntax for referencing an instance variable is as follows:
[classinstance variablename]
Taking our BankAccount example, therefore, we could get the value of our accountNumber instance variable and assign it to a variable named balance1 as follows:
double balance1 = [account1 accountBalance];
Objective-C and Dot Notation
<google>IOSBOX</google> Those familiar with object oriented programming in Java, C++ or C# are probably reeling a little from the syntax used in Objective-C. They are probably thinking life was much easier when they could just use something called dot notation to set and get the values of instance variables. The good news is that one of the features introduced into version 2.0 of Objective-C is support for dot notation.
Dot notation involves accessing an instance variable by specifying a class instance followed by a dot followed in turn by the name of the instance variable or property to be accessed:
classinstance.property
For example, to the get current value of our accountBalance instance variable:
double balance1 = account1.accountBalance;
Dot notation can also be used to set values of instance properties:
account1.accountBalance = 6789.98;
A key point to understand about dot notation is that it only works for instance variables for which synthesized accessor methods have been declared. If you attempt to use dot notation to access an instance variable for which no synthesized accessor is available the code will fail to compile with an error similar to:
error: request for member 'accountBalance' in something not a structure or union
Controlling Access to Instance Variables
- protected - Access is allowed only by methods of the class and any subclasses.
- private - Access is restricted to methods of the class. Access is not available to subclasses.
- public - Direct access available to methods of the class, subclasses and code in other module files and classes.
The access level for instance variables is specified in the @interface section of the class declaration using the @protected, @private and @public directives. Once a directive has been specified, all instance variables beneath that line adopt that setting until another directive is specified. For example:
@interface { double accountBalance; @private long accountNumber; int accessCount; @public float interestRate; }
In the above example, accountbalance will default to protected access since it is not preceded by a directive, accountNumber and accessCount are both private and interestRate is public.
When accessing a public instance variable from another class or any other code in a methods or function, the -> pointer operator notation is used.
For example:
account1->accountBalance = 12345.67;
An attempt to access a non-public instance variable using pointer notation will result in a compiler warning similar to the following:
warning: instance variable 'accountNumber' is @protected; this will be a hard error in the future
Purchase the full edition of this Objective-C book in Print ($14.99) or eBook ($12.99) format Objective-C 2.0 Essentials Print and eBook (ePub/PDF/Kindle) editions contain 31 chapters. |
Previous | Table of Contents | Next |
Writing Objective-C Class Methods | Objective-C Inheritance |