Online Book Reader

Home Category

Objective-C Programming_ The Big Nerd Ranch Guide - Aaron Hillegass [72]

By Root 463 0
self is an instance of OwnedAppliance, so it calls initWithProductName: in OwnedAppliance, which calls [self initWithProductName:pn firstOwnerName:nil].

What you wind up with is a chain of initializers that call other initializers.

Figure 29.3 Initializer chain

Notice that Figure 29.3 shows one shaded initializer for each class. This initializer is the designated initializer for that class. init is the designated initializer for NSObject, initWithProductName: is the designated initializer for Appliance, and initWithProductName:firstOwnerName: is the designated initializer for OwnedAppliance. A class has only one designated initializer method. If the class has other initializers, then the implementation of those initializers must call (directly or indirectly) the designated initializer. Thus, the designated initializer acts as a funnel-point.

When you create a class whose designated initializer has a different name than its superclass’s designated initializer (as you did in Appliance and OwnedAppliance), you have a responsibility to document that in the header file. Add the appropriate comment in Appliance.h:

#import

@interface Appliance : NSObject {

NSString *productName;

int voltage;

}

@property (copy) NSString *productName;

@property int voltage;

// The designated initializer

- (id)initWithProductName:(NSString *)pn;

@end

and in OwnedAppliance.h:

#import "Appliance.h"

@interface OwnedAppliance : Appliance {

NSMutableSet *ownerNames;

}

// The designated initializer

- (id)initWithProductName:(NSString *)pn

firstOwnerName:(NSString *)n;

- (void)addOwnerNamesObject:(NSString *)n;

- (void)removeOwnerNamesObject:(NSString *)n;

@end

Thus, we arrive at the rules that all stylish Objective-C programmers follow when writing initializers:

If a class has several initializers, only one should do the real work. That method is known as the designated initializer. All other initializers should call, either directly or indirectly, the designated initializer.

The designated initializer will call the superclass’s designated initializer before initializing its instance variables.

If the designated initializer of your class has a different name than the designated initializer of its superclass, you must override the superclass’s designated initializer so that it calls the new designated initializer.

If you have several initializers, clearly document which is the designated initializer in the header.

Deadly init methods


Every once in a while, however, you can’t safely override the superclass’s designated initializer. Let’s say that you are creating a subclass of NSObject called WallSafe, and its designated initializer is initWithSecretCode:. However, having a default value for secretCode is not secure enough for your application. This means that the pattern we have been using – overriding init to call the new class’s designated initializer with default values – is not acceptable.

So what do you do? An instance of WallSafe will still respond to an init message. Someone could easily do this:

WallSafe *ws = [[WallSafe alloc] init];

The best thing to do is to override the superclass’s designated initializer in a way that lets developers know that they have made a mistake and tells them how to fix it:

- (id)init

{

@throw [NSException exceptionWithName:@"WallSafeInitialization"

reason:@"Use initWithSecretCode:, not init"

userInfo:nil];

}

30

Properties


In the last chapter, you created a class called Appliance that had two properties: productName and voltage. Let’s review how those properties work.

In Appliance.h, you declared two instance variables to hold the data:

{

NSString *productName;

int voltage;

}

You also declared accessor methods for them. You could have declared the accessors like this:

- (void)setProductName:(NSString *)s;

- (NSString *)productName;

- (void)setVoltage:(int)x;

- (int)voltage;

However, you used the @property construct instead:

@property (copy) NSString *productName;

Return Main Page Previous Page Next Page

®Online Book Reader