Objective-C Programming_ The Big Nerd Ranch Guide - Aaron Hillegass [34]
// and methods defined by the class NSObject
@interface Person : NSObject
{
// It has two instance variables
float heightInMeters;
int weightInKilos;
}
// You will be able to set those instance variables using these methods
- (void)setHeightInMeters:(float)h;
- (void)setWeightInKilos:(int)w;
// This method calculates the Body Mass Index
- (float)bodyMassIndex;
@end
Notice that you declared the instance variables inside of curly braces and you declared the methods after the variables and outside of the curly braces.
To the compiler, this code says “I am defining a new class called Person that has all the methods and instance variables of the class NSObject. Furthermore, I’m adding in two new instance variables: a float called heightInMeters and an int called weightInKilos. Also, I’m going to add three instance methods, which will be implemented in Person.m.”
Notice that setHeightInMeters: expects a float argument and does not return a value, setWeightInKilos: expects an int argument and does not return a value, and bodyMassIndex takes no arguments and returns a float.
Now open Person.m. Delete any existing methods and implement the methods you declared:
#import "Person.h"
@implementation Person
- (void)setHeightInMeters:(float)h
{
heightInMeters = h;
}
- (void)setWeightInKilos:(int)w
{
weightInKilos = w;
}
- (float)bodyMassIndex
{
return weightInKilos / (heightInMeters * heightInMeters);
}
@end
Note that Xcode imported Person.h for you. Also note that the names of the methods you implement must exactly match the ones you declared in the header file. In Xcode, this is easy; as you start typing a method in the implementation file, Xcode will suggest names of methods you’ve already declared.
Now that you’ve implemented all the methods you declared in Person.h, your class is complete. Edit main.m to exercise it a bit:
#import #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 has a BMI of %f", bmi); } return 0; } Build and run the program. Notice that you imported Person.h so that the compiler will know how your methods are declared before they are used in main(). Figure 17.1 Object diagram for BMITime Accessor methods person.weightInKilos = 96; person.heightInMeters = 1.8; In object-oriented thinking, we do our best to keep the instance variables of an object private; that is, they are known and accessed only by the object itself. However, because we want to give methods and functions outside of Person the ability to set a person’s weight and height, we created the methods setWeightInKilos: and setHeightInMeters:. We call these setter methods. A setter method allows other methods to set the value of an instance variable. A getter method allows other methods to read the value of an instance variable. Setter and getter methods are also known as accessor methods, or just accessors. Add declarations for the getter methods to Person.h: #import @interface Person : NSObject { float heightInMeters; int weightInKilos; } // You will be able to set those instance variables - (float)heightInMeters; - (void)setHeightInMeters:(float)h; - (int)weightInKilos; - (void)setWeightInKilos:(int)w; - (float)bodyMassIndex; @end You might wonder why the names of the getter methods don’t include get to match the setter method names. This is an Objective-C naming convention. The name of the method for reading an instance variable is simply the name of that instance variable. Now return
Note that when we did this same exercise with structs instead of objects, we accessed the data members of the structure directly in main():