20
Inheritance

When you created the BNRPerson class, you declared it to be a subclass of NSObject. This means that every instance of BNRPerson will have the instance variables and methods defined in NSObject as well as the instance variables and methods defined in BNRPerson. We say that BNRPerson inherits the instance variables and methods from NSObject.

In this chapter, you are going to create a new class named BNREmployee. BNREmployee will be a subclass of BNRPerson.

Figure 20.1  BNREmployee inherits from BNRPerson

BNREmployee inherits from BNRPerson

Makes sense, right? Employees are people. They have heights and weights. But not all people are employees; employees can have characteristics specific to being an employee. Your BNREmployee class adds two BNREmployee-specific characteristics – an employee ID and a hire date.

Open up the BMITime project and create a new file: an Objective-C class. Name the class BNREmployee and leave its superclass as NSObject for now.

Open BNREmployee.h. Import BNRPerson.h and change the superclass from NSObject to BNRPerson:

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

@​i​n​t​e​r​f​a​c​e​ ​B​N​R​E​m​p​l​o​y​e​e​ ​:​ ​B​N​R​P​e​r​s​o​n​

@​e​n​d​

BNREmployee is now a subclass of BNRPerson.

The main function of BMITime will need to access the employee ID and the hire date. Each employee also has an alarm code to get into the office. Thus, you need three new properties, and you need to add them in BNREmployee.h. Also declare a method that will calculate the years of employment based on the employee’s hire date.

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

@​i​n​t​e​r​f​a​c​e​ ​B​N​R​E​m​p​l​o​y​e​e​ ​:​ ​B​N​R​P​e​r​s​o​n​

@​p​r​o​p​e​r​t​y​ ​(​n​o​n​a​t​o​m​i​c​)​ ​u​n​s​i​g​n​e​d​ ​i​n​t​ ​e​m​p​l​o​y​e​e​I​D​;@​p​r​o​p​e​r​t​y​ ​(​n​o​n​a​t​o​m​i​c​)​ ​u​n​s​i​g​n​e​d​ ​i​n​t​ ​o​f​f​i​c​e​A​l​a​r​m​C​o​d​e​;@​p​r​o​p​e​r​t​y​ ​(​n​o​n​a​t​o​m​i​c​)​ ​N​S​D​a​t​e​ ​*​h​i​r​e​D​a​t​e​;-​ ​(​d​o​u​b​l​e​)​y​e​a​r​s​O​f​E​m​p​l​o​y​m​e​n​t​;​

@​e​n​d​

The hireDate property is the first property you have declared that points to another object. When a property points to an object, there are memory management implications that you will learn about in later chapters.

For now, recognize that you have declared a property named hireDate that is a pointer to an NSDate. You tell the compiler that this property is to be nonatomic, like all the other properties.

Figure 20.2  BNREmployee has a pointer to an NSDate

BNREmployee has a pointer to an NSDate

And, like with your primitive type properties, by default you get an instance variable. This variable is named _hireDate and is a pointer to an NSDate. The compiler also synthesizes two accessor methods:

-​ ​(​v​o​i​d​)​s​e​t​H​i​r​e​D​a​t​e​:​(​N​S​D​a​t​e​ ​*​)​d​;​
-​ ​(​N​S​D​a​t​e​ ​*​)​h​i​r​e​D​a​t​e​;​

In BNREmployee.m, implement the yearsOfEmployment method:

@​i​m​p​l​e​m​e​n​t​a​t​i​o​n​ ​B​N​R​E​m​p​l​o​y​e​e​

-​ ​(​d​o​u​b​l​e​)​y​e​a​r​s​O​f​E​m​p​l​o​y​m​e​n​t{​
 ​ ​ ​ ​/​/​ ​D​o​ ​I​ ​h​a​v​e​ ​a​ ​n​o​n​-​n​i​l​ ​h​i​r​e​D​a​t​e​?​
 ​ ​ ​ ​i​f​ ​(​s​e​l​f​.​h​i​r​e​D​a​t​e​)​ ​{​
 ​ ​ ​ ​ ​ ​ ​ ​/​/​ ​N​S​T​i​m​e​I​n​t​e​r​v​a​l​ ​i​s​ ​t​h​e​ ​s​a​m​e​ ​a​s​ ​d​o​u​b​l​e​
 ​ ​ ​ ​ ​ ​ ​ ​N​S​D​a​t​e​ ​*​n​o​w​ ​=​ ​[​N​S​D​a​t​e​ ​d​a​t​e​]​;​
 ​ ​ ​ ​ ​ ​ ​ ​N​S​T​i​m​e​I​n​t​e​r​v​a​l​ ​s​e​c​s​ ​=​ ​[​n​o​w​ ​t​i​m​e​I​n​t​e​r​v​a​l​S​i​n​c​e​D​a​t​e​:​s​e​l​f​.​h​i​r​e​D​a​t​e​]​;​
 ​ ​ ​ ​ ​ ​ ​ ​r​e​t​u​r​n​ ​s​e​c​s​ ​/​ ​3​1​5​5​7​6​0​0​.​0​;​ ​ ​/​/​ ​S​e​c​o​n​d​s​ ​p​e​r​ ​y​e​a​r​
 ​ ​ ​ ​}​ ​e​l​s​e​ ​{​
 ​ ​ ​ ​ ​ ​ ​ ​r​e​t​u​r​n​ ​0​;​
 ​ ​ ​ ​}}​

@​e​n​d​

To try out the BNREmployee class, open main.m and make two changes: import BNREmployee.h and create an instance of BNREmployee instead of a BNRPerson. Leave the person variable declared as a pointer to a BNRPerson for now:

#​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​m​p​o​r​t​ ​"​B​N​R​E​m​p​l​o​y​e​e​.​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​[​]​)​
{​
 ​ ​ ​ ​@​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​E​m​p​l​o​y​e​e​
 ​ ​ ​ ​ ​ ​ ​ ​B​N​R​P​e​r​s​o​n​ ​*​m​i​k​e​y​ ​=​ ​[​[​B​N​R​E​m​p​l​o​y​e​e​ ​a​l​l​o​c​]​ ​i​n​i​t​]​;​

 ​ ​ ​ ​ ​ ​ ​ ​/​/​ ​G​i​v​e​ ​p​r​o​p​e​r​t​i​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​ ​m​e​t​h​o​d​s​
 ​ ​ ​ ​ ​ ​ ​ ​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​;​

 ​ ​ ​ ​ ​ ​ ​ ​/​/​ ​L​o​g​ ​s​o​m​e​ ​p​r​o​p​e​r​t​i​e​s​ ​u​s​i​n​g​ ​g​e​t​t​e​r​ ​m​e​t​h​o​d​s​
 ​ ​ ​ ​ ​ ​ ​ ​N​S​L​o​g​(​@​"​m​i​k​e​y​ ​h​a​s​ ​a​ ​w​e​i​g​h​t​ ​o​f​ ​%​d​"​,​ ​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​ ​h​a​s​ ​a​ ​h​e​i​g​h​t​ ​o​f​ ​%​f​"​,​ ​m​i​k​e​y​.​h​e​i​g​h​t​I​n​M​e​t​e​r​s​)​;​

 ​ ​ ​ ​ ​ ​ ​ ​/​/​ ​L​o​g​ ​t​h​e​ ​b​o​d​y​ ​m​a​s​s​ ​i​n​d​e​x​
 ​ ​ ​ ​ ​ ​ ​ ​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​;​
}​

Think this will cause a problem? Build and run the program to see.

The program works fine, and nothing in the output has changed. An employee is a person – it can do anything a person can. An instance of BNREmployee can respond to methods from BNRPerson (like setWeightInKilos:). You can use an instance of BNREmployee anywhere that the program expects an instance of BNRPerson. A instance of a subclass can stand in for an instance of the superclass without problems because it inherits everything in the superclass.

Also note that you do not need to import BNRPerson.h. The compiler will find the #import "BNRPerson.h" statement in the BNREmployee.h file, so including it in here would be redundant.

Now make the following changes in main.m to make fuller use of the BNREmployee class. Give mikey an employee ID and set the hire date to the current date.

#​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​E​m​p​l​o​y​e​e​.​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​[​]​)​
{​
 ​ ​ ​ ​@​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​E​m​p​l​o​y​e​e​
 ​ ​ ​ ​ ​ ​ ​ ​B​N​R​E​m​p​l​o​y​e​e​ ​*​m​i​k​e​y​ ​=​ ​[​[​B​N​R​E​m​p​l​o​y​e​e​ ​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​ ​m​e​t​h​o​d​s​
 ​ ​ ​ ​ ​ ​ ​ ​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​;​
 ​ ​ ​ ​ ​ ​ ​ ​m​i​k​e​y​.​e​m​p​l​o​y​e​e​I​D​ ​=​ ​1​2​;​
 ​ ​ ​ ​ ​ ​ ​ ​m​i​k​e​y​.​h​i​r​e​D​a​t​e​ ​=​ ​[​N​S​D​a​t​e​ ​d​a​t​e​W​i​t​h​N​a​t​u​r​a​l​L​a​n​g​u​a​g​e​S​t​r​i​n​g​:​@​"​A​u​g​ ​2​n​d​,​ ​2​0​1​0​"​]​;​

 ​ ​ ​ ​ ​ ​ ​ ​/​/​ ​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​s​"​,​ ​h​e​i​g​h​t​,​ ​w​e​i​g​h​t​)​;​
 ​ ​ ​ ​ ​ ​ ​ ​N​S​L​o​g​(​@​"​E​m​p​l​o​y​e​e​ ​%​u​ ​h​i​r​e​d​ ​o​n​ ​%​@​"​,​ ​m​i​k​e​y​.​e​m​p​l​o​y​e​e​I​D​,​ ​m​i​k​e​y​.​h​i​r​e​D​a​t​e​)​;​

 ​ ​ ​ ​ ​ ​ ​ ​/​/​ ​L​o​g​ ​t​h​e​ ​b​o​d​y​ ​m​a​s​s​ ​i​n​d​e​x​ ​u​s​i​n​g​ ​t​h​e​ ​b​o​d​y​M​a​s​s​I​n​d​e​x​ ​m​e​t​h​o​d​
 ​ ​ ​ ​ ​ ​ ​ ​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​]​;​
 ​ ​ ​ ​ ​ ​ ​ ​d​o​u​b​l​e​ ​y​e​a​r​s​ ​=​ ​[​m​i​k​e​y​ ​y​e​a​r​s​O​f​E​m​p​l​o​y​m​e​n​t​]​;​
 ​ ​ ​ ​ ​ ​ ​ ​N​S​L​o​g​(​@​"​B​M​I​ ​o​f​ ​%​.​2​f​,​ ​h​a​s​ ​w​o​r​k​e​d​ ​w​i​t​h​ ​u​s​ ​f​o​r​ ​%​.​2​f​ ​y​e​a​r​s​"​,​ ​b​m​i​,​ ​y​e​a​r​s​)​;​
 ​ ​ ​ ​}​
 ​ ​ ​ ​r​e​t​u​r​n​ ​0​;​
}​

Build and run the program and see your new output.

Overriding methods

Usually, a subclass needs to do something differently than its superclass. Let’s say, for example, that, unlike people in general, employees always have a BMI of 19. In this case, you would override the bodyMassIndex method in BNREmployee.

You override an inherited method by writing a new implementation.

In BNREmployee.m, override bodyMassIndex:

#​i​m​p​o​r​t​ ​"​B​N​R​E​m​p​l​o​y​e​e​.​h​"​
@​i​m​p​l​e​m​e​n​t​a​t​i​o​n​ ​B​N​R​E​m​p​l​o​y​e​e​

-​ ​(​d​o​u​b​l​e​)​y​e​a​r​s​O​f​E​m​p​l​o​y​m​e​n​t​
{​
 ​ ​ ​ ​/​/​ ​D​o​ ​I​ ​h​a​v​e​ ​a​ ​n​o​n​-​n​i​l​ ​h​i​r​e​D​a​t​e​?​
 ​ ​ ​ ​i​f​ ​(​s​e​l​f​.​h​i​r​e​D​a​t​e​)​ ​{​
 ​ ​ ​ ​ ​ ​ ​ ​/​/​ ​N​S​T​i​m​e​I​n​t​e​r​v​a​l​ ​i​s​ ​t​h​e​ ​s​a​m​e​ ​a​s​ ​d​o​u​b​l​e​
 ​ ​ ​ ​ ​ ​ ​ ​N​S​T​i​m​e​I​n​t​e​r​v​a​l​ ​s​e​c​s​ ​=​ ​[​s​e​l​f​.​h​i​r​e​D​a​t​e​ ​t​i​m​e​I​n​t​e​r​v​a​l​S​i​n​c​e​N​o​w​]​;​
 ​ ​ ​ ​ ​ ​ ​ ​r​e​t​u​r​n​ ​s​e​c​s​ ​/​ ​3​1​5​5​7​6​0​0​.​0​;​ ​ ​/​/​ ​S​e​c​o​n​d​s​ ​p​e​r​ ​y​e​a​r​
 ​ ​ ​ ​}​ ​e​l​s​e​ ​{​
 ​ ​ ​ ​ ​ ​ ​ ​r​e​t​u​r​n​ ​0​;​
 ​ ​ ​ ​}​
}​

-​ ​(​f​l​o​a​t​)​b​o​d​y​M​a​s​s​I​n​d​e​x{​
 ​ ​ ​ ​r​e​t​u​r​n​ ​1​9​.​0​;}​

@​e​n​d​

Because BNREmployee inherits from BNRPerson, everyone already knows that instances of BNREmployee will respond to a bodyMassIndex message. There is no need to advertise it again, so you do not declare it in BNREmployee.h.

This also means that, when you override a method, you can only change its implementation. You cannot change how it is declared; the method’s name, return type, and argument types must stay the same.

Build and run the program. Confirm that BNREmployee’s implementation of bodyMassIndex is the one that gets executed – not the implementation from BNRPerson.

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

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