Должен ли я присвоить результат вызова инициализатора моего класса для себя? - PullRequest
0 голосов
/ 08 декабря 2011

Я читал источник core-plot и наткнулся на этот код в CPTColor:

-(id)initWithCGColor:(CGColorRef)newCGColor
{
    if ( (self = [super init]) ) {            
        CGColorRetain(newCGColor);
        cgColor = newCGColor;
    }
    return self;
}

-(id)initWithComponentRed:(CGFloat)red green:(CGFloat)green blue:(CGFloat)blue alpha:(CGFloat)alpha
{
    CGFloat colorComponents[4];
    colorComponents[0] = red;
    colorComponents[1] = green;
    colorComponents[2] = blue;
    colorComponents[3] = alpha;
    CGColorRef color = CGColorCreate([CPTColorSpace genericRGBSpace].cgColorSpace, colorComponents);
    [self initWithCGColor:color];
    CGColorRelease(color);
    return self;
}

Если [self initWithCGColor:color]; приводит к тому, что суперкласс initWithCGColor присваивает себе другое значениеБудет ли возвращено это новое значение из initWithComponentRed:green:blue:alpha:?

Другими словами, является ли self в двух методах инициализации одной и той же переменной двумя разными переменными?

Ответы [ 3 ]

3 голосов
/ 08 декабря 2011

Эта установка потенциально хрупкая, и предложение Джо, присваивающее self в initWithComponentRed:... перед возвратом этого значения, исправит это.

Каждый метод получает аргумент self, который указывает на экземпляр, к которому он был вызван. Аргумент действует так же, как любая другая переменная; в этом нет ничего особенного. Вот почему можно присвоить self, и поэтому необходимо иметь явный return в инициализаторах.

Когда вы отправляете [super init], вы используете версию суперкласса метода init, но текущий экземпляр все равно будет передан как self. Поскольку инициализаторам в Objective-C разрешено уничтожать полученный ими объект, а также создавать и возвращать новый, * существует вероятность того, что self = [super init] в initWithColor: не будет тем же объектом, на который указывает self назад в initWithComponentRed:....

Если это произойдет, поскольку вы не переназначаете self для указания на этот новый, правильно инициализированный объект, вы будете возвращать неинициализированный объект из initWithComponentRed:....

Это практическая проблема, если ваш суперкласс мог бы выполнить замену, которую я описал, но также нет причины, AFAIK, не делать это переназначение.


* Коллекции делают это, например, потому что они не знают, насколько большим они должны быть в alloc время; Я считаю, что NSNumber также делает это, потому что он кэширует значения для экземпляров, представляющих маленькие целые числа.

2 голосов
/ 08 декабря 2011

Нет, если self изменится (например, если вы собираетесь реализовать цветовой кэш) initWithComponentRed:green:blue:alpha: вернет неправильный объект, если код не был изменен на:

    ...
    self = [self initWithCGColor:color];
    CGColorRelease(color);
    return self;
}
0 голосов
/ 08 декабря 2011

self всегда относится к одному и тому же объекту. Это не "переменная", а ключевое слово языка. Если один инициализатор вызывается после другого, объект просто изменяется.

NB. В противном случае ваш класс будет иметь "раздвоение личности" ;-).

...