Objective-C Programming_ The Big Nerd Ranch Guide - Aaron Hillegass [35]
@implementation Person
- (float)heightInMeters
{
return heightInMeters;
}
- (void)setHeightInMeters:(float)h
{
heightInMeters = h;
}
- (int)weightInKilos
{
return weightInKilos;
}
- (void)setWeightInKilos:(int)w
{
weightInKilos = w;
}
- (float)bodyMassIndex
{
return weightInKilos / (heightInMeters * heightInMeters);
}
@end
Finally, in main.m, use those methods:
#import "Person.h"
int main(int argc, const char * argv[])
{
@autoreleasepool {
// Create an instance of Person
Person *person = [[Person alloc] init];
// Give the instance variables interesting values
[person setWeightInKilos:96];
[person setHeightInMeters:1.8];
// Call the bodyMassIndex method
float bmi = [person bodyMassIndex];
NSLog(@"person (%d, %f) has a BMI of %f",
[person weightInKilos], [person heightInMeters], bmi);
}
return 0;
}
Build and run the program.
Dot notation
Objective-C programmers call accessor methods a lot. Apple decided to create a shortcut for calling an accessor. This shortcut makes these two lines of code exactly the same:
p = [x fido];
p = x.fido;
It also makes these two lines of code exactly the same:
[x setFido:3];
x.fido = 3;
The form that uses the period instead of the square brackets is known as dot notation.
I avoid using dot notation. I feel it obscures the fact that a message is being sent, and it isn’t consistent with the way we do every other message send in the system. You are welcome to use dot notation, but it will not appear anywhere else in this book.
Properties
Notice that most of our code in the Person class is devoted to accessor methods. Apple has created a handy way to simplify writing accessor methods called properties. With a property, you can declare both the setter and getter methods in one line.
In Person.h, replace the declaration of the setter and getter methods with the @property construct:
#import @interface Person : NSObject { float heightInMeters; int weightInKilos; } @property float heightInMeters; @property int weightInKilos; - (float)bodyMassIndex; @end You have not changed this class at all with this edit. You are just using a terser syntax. Now, take a look at the Person.m file. It is chock-full of simple and predictable accessor methods. In the case where your accessors do nothing special, you can just tell the compiler to synthesize default accessor methods based on each @property declaration. Delete the accessors and replace them with a call to @synthesize: #import "Person.h" @implementation Person @synthesize heightInMeters, weightInKilos; - (float)bodyMassIndex { return weightInKilos / (heightInMeters * heightInMeters); } @end Build and run the program. Everything should work the same as before with code that is far simpler and easier to maintain. self - (float)bodyMassIndex { float h = [self heightInMeters]; return [self weightInKilos] / (h * h); } Here an instance of Person sends itself two messages, heightInMeters and weightInKilos, to get the values of its instance variables. You can also pass self as an argument to let other objects know where the current object is. For example, your Person class might have a method addYourselfToArray: that would look like this: - (void)addYourselfToArray:(NSMutableArray *)theArray { [theArray addObject:self]; } Here you use self to tell the array where the instance of Person lives. It is literally its address. Multiple files
Inside any method, you have access to the implicit local variable self. self is a pointer to the object that is running the method. It is used when an object wants to send a message to itself. For example, many Objective-C programmers are quite religious about accessor methods; they never read or write to an instance variable except using its accessor methods. Update your bodyMassIndex method to please the purists:
Notice that your project now has executable code in two files: main.m and