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

syn*_*nic 14 objective-c

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

- (id)initWithTitle:(NSString *)title;
- (id)initWithTitle:(NSString *)title page:(NSString *)page;
Run Code Online (Sandbox Code Playgroud)

第二个构造函数与第一个构造函数没有区别,只是它设置了成员变量"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;
}
Run Code Online (Sandbox Code Playgroud)

phu*_*ehe 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;
}
Run Code Online (Sandbox Code Playgroud)

不行吗?


bbu*_*bum 21

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

- (id)initWithTitle:(NSString *)title;
- (id)initWithTitle:(NSString *)title page:(NSString *)page;
Run Code Online (Sandbox Code Playgroud)

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

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

- (id)initWithTitle:(NSString *)title page:(NSString *)page;
Run Code Online (Sandbox Code Playgroud)

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

- (id)initWithTitle:(NSString *)_title {
    return [self initWithTitle:_title page:nil];
}
Run Code Online (Sandbox Code Playgroud)

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

此外,这:

Foo *f = [[Foo alloc] initWithTitle: @"Foo!" page: nil];
Run Code Online (Sandbox Code Playgroud)

比这更清楚:

Foo *f = [[Foo alloc] initWithTitle: @"Foo!"];
Run Code Online (Sandbox Code Playgroud)

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

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

  • 当您创建引入新初始化程序的类别而您只想调用现有的初始化程序时,无法避免该模式. (2认同)