18
Your First Class

So far, you have only used classes created by Apple. Now you get to write your own class. Remember that a class describes objects in two ways: instance variables within each instance of the class and methods implemented by the class.

You are going to write a BNRPerson class, which will be similar to the struct Person you wrote in Chapter 11. This class, like all Objective-C classes, will be defined in two files:

  • BNRPerson.h is the class’s header and will contain the declarations of instance variables and methods.

  • BNRPerson.m is the implementation file. This is where you write out the code for, or implement, each method.

First, create a new project: a Foundation Command Line Tool named BMITime.

To create a new class, select FileNewFile.... From the OS X section on the left, select Cocoa. Choose the Objective-C class template and click Next.

Figure 18.1  Creating a new class

Creating a new class

Name your class BNRPerson and make it a subclass of NSObject. (You will learn about subclasses and NSObject in Chapter 20.)

Figure 18.2  Naming your new class

Naming your new class

Click Next. Finally, make sure the BMITime target is checked and then click Create.

Find BNRPerson.h and BNRPerson.m in the project navigator. Open BNRPerson.h and declare two instance variables:

#​i​m​p​o​r​t​ ​<​F​o​u​n​d​a​t​i​o​n​/​F​o​u​n​d​a​t​i​o​n​.​h​>​

@​i​n​t​e​r​f​a​c​e​ ​B​N​R​P​e​r​s​o​n​ ​:​ ​N​S​O​b​j​e​c​t​

{​
 ​ ​ ​ ​/​/​ ​B​N​R​P​e​r​s​o​n​ ​h​a​s​ ​t​w​o​ ​i​n​s​t​a​n​c​e​ ​v​a​r​i​a​b​l​e​s​
 ​ ​ ​ ​f​l​o​a​t​ ​_​h​e​i​g​h​t​I​n​M​e​t​e​r​s​;​
 ​ ​ ​ ​i​n​t​ ​_​w​e​i​g​h​t​I​n​K​i​l​o​s​;}​

@​e​n​d​

A header file starts with @interface and finishes off with @end. Notice that you declared the instance variables first and inside of curly braces.

By convention, instance variable names start with an underscore (_). Using the underscore prefix lets you easily tell instance variables from local variables when reading code. The underscore does not mean anything special to the compiler; it is simply the first character in the instance variable’s name.

Next, declare five instance methods after the instance variables and outside of the curly braces:

#​i​m​p​o​r​t​ ​<​F​o​u​n​d​a​t​i​o​n​/​F​o​u​n​d​a​t​i​o​n​.​h​>​

@​i​n​t​e​r​f​a​c​e​ ​B​N​R​P​e​r​s​o​n​ ​:​ ​N​S​O​b​j​e​c​t​

{​
 ​ ​ ​ ​/​/​ ​B​N​R​P​e​r​s​o​n​ ​h​a​s​ ​t​w​o​ ​i​n​s​t​a​n​c​e​ ​v​a​r​i​a​b​l​e​s​
 ​ ​ ​ ​f​l​o​a​t​ ​_​h​e​i​g​h​t​I​n​M​e​t​e​r​s​;​
 ​ ​ ​ ​i​n​t​ ​_​w​e​i​g​h​t​I​n​K​i​l​o​s​;​
}​

/​/​ ​B​N​R​P​e​r​s​o​n​ ​h​a​s​ ​m​e​t​h​o​d​s​ ​t​o​ ​r​e​a​d​ ​a​n​d​ ​s​e​t​ ​i​t​s​ ​i​n​s​t​a​n​c​e​ ​v​a​r​i​a​b​l​e​s-​ ​(​f​l​o​a​t​)​h​e​i​g​h​t​I​n​M​e​t​e​r​s​;-​ ​(​v​o​i​d​)​s​e​t​H​e​i​g​h​t​I​n​M​e​t​e​r​s​:​(​f​l​o​a​t​)​h​;-​ ​(​i​n​t​)​w​e​i​g​h​t​I​n​K​i​l​o​s​;-​ ​(​v​o​i​d​)​s​e​t​W​e​i​g​h​t​I​n​K​i​l​o​s​:​(​i​n​t​)​w​;/​/​ ​B​N​R​P​e​r​s​o​n​ ​h​a​s​ ​a​ ​m​e​t​h​o​d​ ​t​h​a​t​ ​c​a​l​c​u​l​a​t​e​s​ ​t​h​e​ ​B​o​d​y​ ​M​a​s​s​ ​I​n​d​e​x-​ ​(​f​l​o​a​t​)​b​o​d​y​M​a​s​s​I​n​d​e​x​;​

@​e​n​d​

To return to BNRPerson.m, use the keyboard shortcut Control-Command-up arrow. This shortcut moves you back and forth between the header and implementation files of a class.

Implement the methods that you declared in BNRPerson.h. The methods that you implement must exactly match the ones that you declared in the header. In Xcode, this is easy; when you start typing a method in the implementation file, Xcode will suggest names of methods that you have already declared.

#​i​m​p​o​r​t​ ​"​B​N​R​P​e​r​s​o​n​.​h​"​

@​i​m​p​l​e​m​e​n​t​a​t​i​o​n​ ​B​N​R​P​e​r​s​o​n​

-​ ​(​f​l​o​a​t​)​h​e​i​g​h​t​I​n​M​e​t​e​r​s{​
 ​ ​ ​ ​r​e​t​u​r​n​ ​_​h​e​i​g​h​t​I​n​M​e​t​e​r​s​;}-​ ​(​v​o​i​d​)​s​e​t​H​e​i​g​h​t​I​n​M​e​t​e​r​s​:​(​f​l​o​a​t​)​h{​
 ​ ​ ​ ​_​h​e​i​g​h​t​I​n​M​e​t​e​r​s​ ​=​ ​h​;}-​ ​(​i​n​t​)​w​e​i​g​h​t​I​n​K​i​l​o​s{​
 ​ ​ ​ ​r​e​t​u​r​n​ ​_​w​e​i​g​h​t​I​n​K​i​l​o​s​;}-​ ​(​v​o​i​d​)​s​e​t​W​e​i​g​h​t​I​n​K​i​l​o​s​:​(​i​n​t​)​w{​
 ​ ​ ​ ​_​w​e​i​g​h​t​I​n​K​i​l​o​s​ ​=​ ​w​;}-​ ​(​f​l​o​a​t​)​b​o​d​y​M​a​s​s​I​n​d​e​x{​
 ​ ​ ​ ​r​e​t​u​r​n​ ​_​w​e​i​g​h​t​I​n​K​i​l​o​s​ ​/​ ​(​_​h​e​i​g​h​t​I​n​M​e​t​e​r​s​ ​*​ ​_​h​e​i​g​h​t​I​n​M​e​t​e​r​s​)​;}​

@​e​n​d​

Now that you have implemented the methods that you declared in BNRPerson.h, the BNRPerson class is complete and you can use it in a program.

Open main.m and import BNRPerson.h so that main() can see the declarations in the BNRPerson class header:

#​i​m​p​o​r​t​ ​<​F​o​u​n​d​a​t​i​o​n​/​F​o​u​n​d​a​t​i​o​n​.​h​>​
#​i​m​p​o​r​t​ ​"​B​N​R​P​e​r​s​o​n​.​h​"​

i​n​t​ ​m​a​i​n​(​i​n​t​ ​a​r​g​c​,​ ​c​o​n​s​t​ ​c​h​a​r​ ​*​ ​a​r​g​v​[​]​)​
{​
 ​ ​ ​ ​.​.​.​
}​

Why is Foundation.h inside angled brackets and BNRPerson.h inside quotation marks? The angled brackets tell the compiler that Foundation/Foundation.h is a precompiled header found in Apple’s libraries. The quotation marks tell the compiler to look for BNRPerson.h within the current project.

Next, add code to main() that uses the BNRPerson class:

i​n​t​ ​m​a​i​n​(​i​n​t​ ​a​r​g​c​,​ ​c​o​n​s​t​ ​c​h​a​r​ ​*​ ​a​r​g​v​[​]​)​
{​
 ​ ​ ​ ​@​a​u​t​o​r​e​l​e​a​s​e​p​o​o​l​ ​{​

 ​ ​ ​ ​ ​ ​ ​ ​/​/​ ​C​r​e​a​t​e​ ​a​n​ ​i​n​s​t​a​n​c​e​ ​o​f​ ​B​N​R​P​e​r​s​o​n​
 ​ ​ ​ ​ ​ ​ ​ ​B​N​R​P​e​r​s​o​n​ ​*​m​i​k​e​y​ ​=​ ​[​[​B​N​R​P​e​r​s​o​n​ ​a​l​l​o​c​]​ ​i​n​i​t​]​;​

 ​ ​ ​ ​ ​ ​ ​ ​/​/​ ​G​i​v​e​ ​t​h​e​ ​i​n​s​t​a​n​c​e​ ​v​a​r​i​a​b​l​e​s​ ​i​n​t​e​r​e​s​t​i​n​g​ ​v​a​l​u​e​s​ ​u​s​i​n​g​ ​s​e​t​t​e​r​s​
 ​ ​ ​ ​ ​ ​ ​ ​[​m​i​k​e​y​ ​s​e​t​W​e​i​g​h​t​I​n​K​i​l​o​s​:​9​6​]​;​
 ​ ​ ​ ​ ​ ​ ​ ​[​m​i​k​e​y​ ​s​e​t​H​e​i​g​h​t​I​n​M​e​t​e​r​s​:​1​.​8​]​;​

 ​ ​ ​ ​ ​ ​ ​ ​/​/​ ​L​o​g​ ​t​h​e​ ​i​n​s​t​a​n​c​e​ ​v​a​r​i​a​b​l​e​s​ ​u​s​i​n​g​ ​t​h​e​ ​g​e​t​t​e​r​s​
 ​ ​ ​ ​ ​ ​ ​ ​f​l​o​a​t​ ​h​e​i​g​h​t​ ​=​ ​[​m​i​k​e​y​ ​h​e​i​g​h​t​I​n​M​e​t​e​r​s​]​;​
 ​ ​ ​ ​ ​ ​ ​ ​i​n​t​ ​w​e​i​g​h​t​ ​=​ ​[​m​i​k​e​y​ ​w​e​i​g​h​t​I​n​K​i​l​o​s​]​;​
 ​ ​ ​ ​ ​ ​ ​ ​N​S​L​o​g​(​@​"​m​i​k​e​y​ ​i​s​ ​%​.​2​f​ ​m​e​t​e​r​s​ ​t​a​l​l​ ​a​n​d​ ​w​e​i​g​h​s​ ​%​d​ ​k​i​l​o​g​r​a​m​s​"​,​ ​h​e​i​g​h​t​,​ ​w​e​i​g​h​t​)​;​

 ​ ​ ​ ​ ​ ​ ​ ​/​/​ ​L​o​g​ ​s​o​m​e​ ​v​a​l​u​e​s​ ​u​s​i​n​g​ ​c​u​s​t​o​m​ ​m​e​t​h​o​d​s​
 ​ ​ ​ ​ ​ ​ ​ ​f​l​o​a​t​ ​b​m​i​ ​=​ ​[​m​i​k​e​y​ ​b​o​d​y​M​a​s​s​I​n​d​e​x​]​;​
 ​ ​ ​ ​ ​ ​ ​ ​N​S​L​o​g​(​@​"​m​i​k​e​y​ ​h​a​s​ ​a​ ​B​M​I​ ​o​f​ ​%​f​"​,​ ​b​m​i​)​;​

 ​ ​ ​ ​}​
 ​ ​ ​ ​r​e​t​u​r​n​ ​0​;​
}​

Build and run the program.

Figure 18.3  Object diagram for BMITime

Object diagram for BMITime

Accessor methods

When you created struct Person back in Chapter 11, you accessed the data members of the structure directly in main():

 ​ ​ ​ ​m​i​k​e​y​.​w​e​i​g​h​t​I​n​K​i​l​o​s​ ​=​ ​9​6​;​
 ​ ​ ​ ​m​i​k​e​y​.​h​e​i​g​h​t​I​n​M​e​t​e​r​s​ ​=​ ​1​.​8​;​

In object-oriented thinking, however, code that is outside of a class should not directly read or write to the instance variables of an instance of that class. Only code within the class can do that.

Instead, a class will provide methods that let external code (like in main()) access the instance variables of an instance. This is what you have done in BNRPerson. In main(), you send messages to the BNRPerson instance to read the values of its instance variables:

 ​ ​ ​ ​i​n​t​ ​w​e​i​g​h​t​ ​=​ ​[​m​i​k​e​y​ ​w​e​i​g​h​t​I​n​K​i​l​o​s​]​;​
 ​ ​ ​ ​f​l​o​a​t​ ​h​e​i​g​h​t​ ​=​ ​[​m​i​k​e​y​ ​h​e​i​g​h​t​I​n​M​e​t​e​r​s​]​;​

The heightInMeters and weightInKilos methods are getter methods. A getter method, or getter, allows code outside of a class to read, or get, the value of an instance variable.

BNRPerson also has the methods setHeightInMeters: and setWeightInKilos:. These are setter methods. A setter method, or setter, allows code outside of a class to change, or set, the value of an instance variable.

Setter and getter methods are collectively known as accessor methods, or simply accessors.

Accessor naming conventions

In declaring accessor methods for BNRPerson, you followed important Objective-C naming conventions. Getter methods are given the name of the instance variable minus the underscore.

/​/​ ​I​n​s​t​a​n​c​e​ ​v​a​r​i​a​b​l​e​ ​d​e​c​l​a​r​a​t​i​o​n​s​
{​
 ​ ​ ​ ​f​l​o​a​t​ ​_​h​e​i​g​h​t​I​n​M​e​t​e​r​s​;​
 ​ ​ ​ ​i​n​t​ ​_​w​e​i​g​h​t​I​n​K​i​l​o​s​;​
}​

/​/​ ​G​e​t​t​e​r​ ​m​e​t​h​o​d​ ​d​e​c​l​a​r​a​t​i​o​n​s​
-​ ​(​f​l​o​a​t​)​h​e​i​g​h​t​I​n​M​e​t​e​r​s​;​
-​ ​(​i​n​t​)​w​e​i​g​h​t​I​n​K​i​l​o​s​;​

Setter methods start with set followed by the name of the instance variable minus the underscore. Notice that the case of the setter’s name adjusts to preserve the camel-casing. Thus, the first letter of the instance variable name is uppercase in the setter’s name.

/​/​ ​S​e​t​t​e​r​ ​m​e​t​h​o​d​ ​d​e​c​l​a​r​a​t​i​o​n​s​ ​-​ ​n​o​t​i​c​e​ ​d​i​f​f​e​r​e​n​c​e​ ​i​n​ ​c​a​s​i​n​g​!​
-​ ​(​v​o​i​d​)​s​e​t​H​e​i​g​h​t​I​n​M​e​t​e​r​s​:​(​f​l​o​a​t​)​h​;​
-​ ​(​v​o​i​d​)​s​e​t​W​e​i​g​h​t​I​n​K​i​l​o​s​:​(​i​n​t​)​w​;​

Learning these conventions is important. In the next chapter, you will learn a shortcut where the compiler creates accessor methods for you. The compiler will name the accessors according to these conventions.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset