target-c - вызов одного конструктора из другого - PullRequest
14 голосов
/ 15 мая 2010

Допустим, у вас есть следующие два конструктора:

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

Второй конструктор не отличается от первого, за исключением того, что он устанавливает переменную-член "page".

Поскольку онв основном нужно делать то же самое, есть ли способ вызвать первый из второго, чтобы уменьшить дублирование кода, или вам нужно настроить третий метод для выполнения общих задач?

I 'Я говорю о чем-то похожем на это, хотя я сомневаюсь, что это сработает:

- (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 ]

21 голосов
/ 15 мая 2010

Во-первых, у вас нет конструкторов, у вас есть два инициализатора:

- (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 для разумной установки страницы. Второй не дает такого указания.

Как создание подклассов, так и явное указание намерения являются основными причинами отсутствия таких удобных методов в Какао (есть некоторые, но большинство из них довольно старые - старше, чем когда политика действительно стала правилом). *

21 голосов
/ 15 мая 2010

То, что вы говорите, странно, потому что я думаю об этом

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

Разве это не работает?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...