(Цель-C) Безопасно ли переопределять себя в методе класса? - PullRequest
0 голосов
/ 06 апреля 2011

Безопасно ли повторно инициализировать себя в методе класса?

MyClass * a = [[MyClass alloc]init];

@implementation MyClass
{
    -(id)init
    {
        if(self = [super init])
        {
            ...
        }
        return self;
    }
    -(void)redefine
    {
         //??
         self = [self init];

    }

}

будет a указывать на повторно инициализированный экземпляр MyClass?

Спасибо, nonono

Ответы [ 3 ]

1 голос
/ 06 апреля 2011

При условии , что (a) ваш класс и его суперклассы могут быть перезаписаны без потери памяти или ресурсов и (b) вы знаете, что ваш класс и его суперклассы init все вернуть self они переданы, а не ссылку на какой-то другой объект, тогда да ...

В противном случае все пойдет не так. Рассмотрим ваш redefine метод; в теле этого метода self - просто локальная переменная, содержимое которой инициализируется, чтобы указывать на некоторый объект. Изменение значения в этой локальной переменной не изменяет объект, на который она первоначально указывала, или значение любых других переменных, которые указывают на этот объект. Например. рассмотрим вариант:

@implementation Q
{
    - (void) redefine
    {
         self = [[Q alloc] init]; // changes the *local* self to refer to a new object
    }
    ...
}

...
Q *someQ = [[Q alloc] init];     // allocate an object
[someQ redefine];                // NO effect on someQ, another Q is just created and leaked

Очевидно, что это не меняет someQ, и ваша версия также не может измениться. Ваш код будет иметь желаемый эффект тогда и только тогда, когда вы знаете, init всегда возвращает объект, который был передан - что не гарантируется в Obj-C.

0 голосов
/ 06 апреля 2011

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

// Bad example! Do NOT do this!
Foo *foo = [Foo alloc];
[foo init];

Это анти-шаблон, потому что -init это , а не , требуемый для возврата того же объектабыл вызван на.Это означает, что приведенное выше может в конечном итоге назначить foo для указания на освобожденный объект, а не на объект, который был инициализирован вместо него.Вот почему вы всегда видите +alloc и `init, соединенные вместе, вот так:

Foo *foo = [[Foo alloc] init];

Также вам нужно переназначить себя при вызове супер-символов -init, потому что оно может также вернуть другоеобъект.

self = [super init];
0 голосов
/ 06 апреля 2011

Пока init возвращает self, что обычно происходит, ничто не пойдет не так.

Но вы, вероятно, хотите разделить свою инициализацию на какой-то отдельный метод, который вы можете вызывать из обоих init и redefine.

...