开发者

objective-c - calling one constructor from another

开发者 https://www.devze.com 2022-12-30 04:18 出处:网络
Say you had the following two constructors: - (id)initWithTitle:(NSString *)title; - (id)initWithTitle:(NSString *)title page:(NSString *)page;

Say you had the following two constructors:

- (id)initWithTitle:(NSString *)title;
- (id)initWithTitle:(NSString *)title page:(NSString *)page;

The second constructor is no different from the first, except that it sets up the member variable "page".

Since it basically has to do the same thing, is there a way to call the first one from the second one to reduce code duplication, or do you have to set up a third method to do the common tasks?

I'm talking about something similar to this, though I doubt this will work:

- (id)initWithTitle:(NSString *)_title {
    if(self = [super init]) {
        self.title = _title;
    }

    return self;
}

- (id)initWithTitle:(NSString *)_title page:(NSString *开发者_如何学JAVA)_page {
     if(self = [self initWithTitle:_title]) {
         self.page = _page;
     }

     return self;
}


What you are saying is weird because I'm thinking of this

- (id)initWithTitle:(NSString *)_title {
    return [self initWithTitle:_title page:nil];
}

- (id)initWithTitle:(NSString *)_title page:(NSString *)_page {
    if(self = [super init]) {
        self.title = _title;
        self.page = _page;
    }
    return self;
}

Doesn't it work?


First, you don't have constructors, you have two initializers:

- (id)initWithTitle:(NSString *)title;
- (id)initWithTitle:(NSString *)title page:(NSString *)page;

As with most initializers, the goal is to setup some instance variables (not member variables).

The first step is to identify your designated initializer. In your case, it could be:

- (id)initWithTitle:(NSString *)title page:(NSString *)page;

Which means that - (id)initWithTitle:(NSString *)title; would be implemented as others have described:

- (id)initWithTitle:(NSString *)_title {
    return [self initWithTitle:_title page:nil];
}

However, I would recommend against this pattern as it makes subclassing more error prone than it should be. In subclassing, you must always override the designated initializer or you must implement a new initializer that calls the designated initializer. Obviously, the more initializers you have, the more potential for bugs in subclassing you might introduce.

Furthermore, this:

Foo *f = [[Foo alloc] initWithTitle: @"Foo!" page: nil];

Is far more clear than this:

Foo *f = [[Foo alloc] initWithTitle: @"Foo!"];

The first indicates quite specifically that you have thought about page and decided to explicitly set it to nil or otherwise rely on the class Foo to set the page reasonably. The second gives no such indication.

Both subclassing and explicit indication of intention are the primary reasons why you will find a lack of such convenience methods across Cocoa (there are some, but most are quite old -- older than when the policy really became rule).

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号