Objective-c - вызов одного конструктора из другого
Скажем, у вас были следующие два конструктора:
- (id)initWithTitle:(NSString *)title;
- (id)initWithTitle:(NSString *)title page:(NSString *)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;
}
Ответы
Ответ 1
То, что вы говорите, странно, потому что я думаю об этом
- (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;
}
Не работает ли он?
Ответ 2
Во-первых, у вас нет конструкторов, у вас есть два инициализатора:
- (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];
}
Однако я бы рекомендовал против этого шаблона, поскольку он делает подкласс более подверженным ошибкам, чем должен быть. В подклассе вы должны всегда переопределять назначенный инициализатор, или вы должны реализовать новый инициализатор, который вызывает назначенный инициализатор. Очевидно, чем больше инициализаторов у вас есть, тем больше возможностей для ошибок в подклассе вы можете ввести.
Кроме того, это:
Foo *f = [[Foo alloc] initWithTitle: @"Foo!" page: nil];
Яснее, чем это:
Foo *f = [[Foo alloc] initWithTitle: @"Foo!"];
Первое указывает на то, что вы подумали о page
и решили явно установить его на nil
или иначе полагаться на класс Foo
, чтобы установить страницу разумно. Второй не дает такого указания.
Оба подкласса и явное указание намерения являются основными причинами, по которым вы найдете недостаток таких методов удобства в Cocoa (есть некоторые, но большинство из них довольно старые - старше, чем когда политика действительно стала правилом).