Search code examples
objective-csubclassaccessorivardeclared-property

Setting default values for inherited property without using accessor


I always see people debating whether or not to use a property's setter in the -init method. My problem is how to create a default value in a subclass for an inherited property. Say we have a class called NSLawyer -- a framework class, that I can't change -- with an interface that looks like this:

@interface NSLawyer : NSObject {
    @private
    NSUInteger _numberOfClients;
}

@property (nonatomic, assign) NSUInteger numberOfClients;

@end

And an implementation that looks like this:

@implementation NSLawyer

- (instancetype)init
{
    self = [super init];
    if (self) {
        _numberOfClients = 0;
    }
    return self;
}

@end

Now let's say I want to extend NSLawyer. My subclass will be called SeniorPartner. And since a senior partner should have lots of clients, when SeniorPartner gets initialized, I don't want the instance to start with 0; I want it to have 10. Here's SeniorPartner.m:

@implementation SeniorPartner

- (instancetype)init
{
    self = [super init];
    if (self) {

        // Attempting to set the ivar directly will result in the compiler saying, 
        // "Instance variable _numberOfClients is private."

        // _numberOfClients = 10; <- Can't do this.

        // Thus, the only way to set it is with the mutator:
        self.numberOfClients = 10;

        // Or: [self setNumberOfClients:10];
    }
    return self;
}

@end

So what's a Objective-C newcomer to do? Well, I mean, there's only one thing I can do, and that's set the property. Unless there's something I'm missing. Any ideas, suggestions, tips, or tricks?


Solution

  • You should do exactly has you have; call the accessor. The declaring class typically avoids calling its own accessors in init to avoid accidentally calling an overridden accessor in a subclass that might rely on the consistency of data you haven't initialized yet. Your superclass on the other hand should be completely consistent by the time the subclass's init is run, so there is no problem using superclass accessors at that time.

    Consider the common and general case: you want to set your transform in a UIView subclass. How would you solve that other than call setTransform:? Subclassing non-Apple code is no different.