Что делать с бесполезным init? - PullRequest
1 голос
/ 01 ноября 2011

Это в настоящее время то, что у меня есть для моего init,

- (id)init 
{
    self = [super init];

    if (self) {
        self.url = [[NSURL alloc] init];
        self.blurb = [[NSString alloc] init];
        self.author = [[NSString alloc] init];
    }

    return self;
}

. Он ничего не делает, но у меня есть другой метод с именем initWithObject:, который будет использовать свой аргумент для заполнения переменных экземпляра * 1006.*, blurb и author.Я не знаю, что мне делать с этим init.Должен ли я бросить исключение?Какие еще варианты у меня есть?

Ответы [ 5 ]

11 голосов
/ 01 ноября 2011

Если вы хотите переопределить ваш стандартный метод -init, вы можете либо вернуть nil (если вы не хотите использовать -init), либо сделать:

- (instancetype)init
{
    return [self initWithObject:nil];
}

Если вы хотите полностью прекратить использование -init, вы можете пометить его как недоступный атрибут или использовать NSAssert:

// .h
// ...

- (instancetype)init UNAVAILABLE_ATTRIBUTE;

// ...

// .m
- (instancetype)init
{
    NSAssert(NO, @"This method should not be used");
    return nil;
}

Вы можете использовать UNAVAILABLE_ATTRIBUTE или NSAssert(), но если вы используете UNAVAILABLE_ATTRIBUTE, вам нужна какая-то реализация -init, даже если она просто возвращает nil.

3 голосов
/ 01 ноября 2011

Правило, которое Apple установило для программирования Какао, состоит в том, что у каждого класса должен быть один метод инициализатора, который является "Назначенным инициализатором" . Любой другой инициализатор для класса должен называть это D.I. * D.I. сам должен назвать Д.И. суперкласса Как правило, инициализатор с наибольшим числом аргументов (тот, который наиболее полно указывает состояние нового объекта) - это D.I.

В вашем случае с голыми init и initWithObject: вторым, скорее всего, будет D.I. Поэтому вы должны переопределить init для вызова initWithObject: с некоторым аргументом по умолчанию:

- (id) init {

    return [self initWithObject:[Object objectWithURL:[NSURL URLWithString:@"http://www.apple.com"]
                                                blurb:@""
                                               author:@""]];
}

Это приведет к созданию своего рода фиктивного объекта, который правильно инициализируется с бесполезными данными. (За пределами ARC обязательно следите за управлением памятью аргумента (-ов) по умолчанию - вы хотите использовать автоматически выпущенный / неизвестный объект (-ы).)

* Иногда делается исключение для initWithCoder:.

3 голосов
/ 01 ноября 2011

Я думаю, что вы неверно истолковали то, что прочитали.Я не думаю, что вы бы бросили исключение.Вы могли бы;однако утечка памяти.Если ваш метод initWithObject: выглядит следующим образом:

- (id)initWithObject:(id)obj {
     if ((self = [self init])) {
              self.url=[obj url];
              self.blurb=[obj blurb];
              self.author=[obj author];
     }
     return self;
}

И все будет в порядке.Вы можете получить исключение, если ваш объект был создан с помощью -init, и вы использовали переменную, которая была присвоена, предполагая, что это реально.Поэтому в ваших последующих методах обязательно проверяйте, существуют ли объекты перед их использованием.

Если вы создали свой объект с -init вместо -initWithObject, это может вызвать исключение:

- (void)dealloc {
         [url release];
         [blurb release];
         [author release];
         [super dealloc];
}
3 голосов
/ 01 ноября 2011

Вам не нужно иметь простой init - вы можете просто использовать свой initWithObject: метод.Если вы выполняете какую-либо базовую настройку, которая останется неизменной в 80% случаев, или если у вас есть какой-то общий код во всех ваших инициализаторах, вы можете переопределить init, но это не требуется.

Также рассмотрите возможность изменения вашего initWithObject: имени, чтобы оно было более конкретным, например, initWithPost: (я предполагаю, что это какой-то сборщик записей в блогах, основанный на ваших иварах), чтобы было более очевидно, какой объект нужен.

1 голос
/ 01 ноября 2011

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

...