objective-c - 从另一个构造函数调用

时间:2010-05-15 14:10:40

标签: objective-c

假设你有以下两个构造函数:

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

第二个构造函数与第一个构造函数没有区别,只是它设置了成员变量“page”。

因为它基本上必须做同样的事情,有没有办法从第二个调用第一个来减少代码重复,或者你是否必须设置第三个方法来执行常见任务?

我正在谈论类似的事情,但我怀疑这会奏效:

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

    return self;
}

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

     return self;
}

2 个答案:

答案 0 :(得分:21)

你说的是奇怪的,因为我正在考虑这个

- (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;
}

不起作用吗?

答案 1 :(得分:21)

首先,你没有构造函数,你有两个初始化器:

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

与大多数初始化程序一样,目标是设置一些实例变量(而不是成员变量)。

第一步是识别您指定的初始化程序。在你的情况下,它可能是:

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

这意味着- (id)initWithTitle:(NSString *)title;将像其他人描述的那样实现:

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

但是,我建议不要使用这种模式,因为它使子类化更容易出错。在子类化中,必须始终覆盖指定的初始化程序,您必须实现一个调用指定初始化程序的新初始化程序。显然,你拥有的初始化程序越多,你可能引入的子类化中的bug就越多。

此外,这:

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

远比这更清楚:

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

第一个非常具体地表明您已考虑page并决定明确将其设置为nil或以其他方式依赖类Foo来合理设置页面。第二个没有给出这样的指示。

潜在的子类化和明确的意图指示是你在Cocoa中找到缺乏这种便利方法的主要原因(有一些,但大多数都很老 - 比政策真正成为规则时更老)。