22
Class Extensions

So far, you have declared all of your properties, instance variables, and methods in the class header file. The header is where a class advertises its properties and methods so that other objects will know how to interact with it.

However, not every property or method should be advertised in a class’s header. Some properties or methods may only be intended for use by the class or instances of the class. Such internal details are better declared in a class extension. A class extension is a set of declarations that is private. Only the class or instances of the class are able to use the properties, instance variables, or methods declared in a class extension.

For example, the officeAlarmCode property of BNREmployee should be private. The employee object needs to be able to access its alarm code, while non-employee objects do not need access to the alarm code and should not have it. You can make this happen by moving the declaration of officeAlarmCode from the header (BNREmployee.h) to a class extension.

Typically, class extensions are added to the class implementation file above the @implementation block where methods are implemented. In BNREmployee.m, create a class extension. Then declare the officeAlarmCode property there:

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


/​/​ ​A​ ​c​l​a​s​s​ ​e​x​t​e​n​s​i​o​n​
@​i​n​t​e​r​f​a​c​e​ ​B​N​R​E​m​p​l​o​y​e​e​ ​(​)​

@​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​;​

@​e​n​d​


@​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​

.​.​.​

A class extension starts with @interface and finishes off with @end. In fact, an extension looks a lot like a header, and both are known as interfaces. However, in an extension, instead of the colon and the superclass name found in the header, there is a pair of empty parentheses.

In BNREmployee.h, remove the officeAlarmCode declaration:

#​i​m​p​o​r​t​ ​"​B​N​R​P​e​r​s​o​n​.​h​"​
@​c​l​a​s​s​ ​B​N​R​A​s​s​e​t​;​

@​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​
{​
 ​ ​ ​ ​N​S​M​u​t​a​b​l​e​A​r​r​a​y​ ​*​_​a​s​s​e​t​s​
}​
@​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​;​
@​p​r​o​p​e​r​t​y​ ​(​n​o​n​a​t​o​m​i​c​,​ ​c​o​p​y​)​ ​N​S​A​r​r​a​y​ ​*​a​s​s​e​t​s​;​
-​ ​(​v​o​i​d​)​a​d​d​A​s​s​e​t​:​(​B​N​R​A​s​s​e​t​ ​*​)​a​;​
-​ ​(​u​n​s​i​g​n​e​d​ ​i​n​t​)​v​a​l​u​e​O​f​A​s​s​e​t​s​;​

@​e​n​d​

Build and run the program. Its behavior has not changed. However, moving the officeAlarmCode declaration to a class extension has two related effects:

First, objects that are not instances of BNREmployee can no longer see this property. For instance, a non-BNREmployee object could attempt to access an employee’s alarm code like this:

 ​ ​ ​ ​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​]​;​
 ​ ​ ​ ​u​n​s​i​g​n​e​d​ ​i​n​t​ ​m​i​k​e​y​s​C​o​d​e​ ​=​ ​m​i​k​e​y​.​o​f​f​i​c​e​A​l​a​r​m​C​o​d​e​;​

This attempt would result in a compiler error that reads No visible @interface declares the instance method officeAlarmCode. The only interface that is visible to a non-BNREmployee object is the BNREmployee header. And because the officeAlarmCode property is declared in a class extension rather than in the header, it is not visible (and as such, is unavailable) to non-BNREmployee objects.

Second, the BNREmployee header has one less declaration and thus is a little bit simpler. This is a good thing. The header is intended to be a billboard; its job is to advertise what other developers need to know to make your class work in the code that they write. Too much information makes a header difficult to for other developers to read and use.

Hiding mutability

Now let’s look at a slightly different case for putting a declaration in a class extension instead of the class’s header. In BNREmployee.h, you declared an assets property that is an NSArray, an addAsset: method, and an _assets instance variable that is an NSMutableArray. A developer will see both the property and the instance variable advertised in the header and will be uncertain which you intended outsiders to use.

Now that you know about class extensions, the solution is simple: move the _assets instance variable to BNREmployee’s class extension. In BNREmployee.m, add this declaration:

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

/​/​ ​A​ ​c​l​a​s​s​ ​e​x​t​e​n​s​i​o​n​
@​i​n​t​e​r​f​a​c​e​ ​B​N​R​E​m​p​l​o​y​e​e​ ​(​)​
{​
 ​ ​ ​ ​N​S​M​u​t​a​b​l​e​A​r​r​a​y​ ​*​_​a​s​s​e​t​s​;}​

@​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​;​

@​e​n​d​

@​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​

.​.​.​

In BNREmployee.h, remove the _assets declaration:

#​i​m​p​o​r​t​ ​"​B​N​R​P​e​r​s​o​n​.​h​"​
@​c​l​a​s​s​ ​B​N​R​A​s​s​e​t​;​

@​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​
{​
 ​ ​ ​ ​N​S​M​u​t​a​b​l​e​A​r​r​a​y​ ​*​_​a​s​s​e​t​s}​
@​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​)​ ​N​S​D​a​t​e​ ​*​h​i​r​e​D​a​t​e​;​
@​p​r​o​p​e​r​t​y​ ​(​n​o​n​a​t​o​m​i​c​,​ ​c​o​p​y​)​ ​N​S​A​r​r​a​y​ ​*​a​s​s​e​t​s​;​
-​ ​(​v​o​i​d​)​a​d​d​A​s​s​e​t​:​(​B​N​R​A​s​s​e​t​ ​*​)​a​;​
-​ ​(​u​n​s​i​g​n​e​d​ ​i​n​t​)​v​a​l​u​e​O​f​A​s​s​e​t​s​;​

@​e​n​d​

Now the array of assets is only advertised as an immutable array, so non-BNREmployee objects will need to use the addAsset: method to manipulate this array. The fact that there is an NSMutableArray instance backing the assets property is a private implementation detail of the BNREmployee class.

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

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