简体   繁体   English

(Objective-C)在类方法中重新定义自身是否安全?

[英](Objective-C)Is it safe to redefine self within class method?

Is it safe to reinitialise self within a class method? 在类方法中重新初始化self是否安全?

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

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

    }

}

will a point to the reinitialized instance of MyClass? a点的MyClass重新初始化实例?

Thank You, nonono 谢谢,nonono

Provided that (a) your class and its superclasses can be re- init 'ed without leaking memory or resources and (b) you know that your class and its superclasses init s all return the self they are passed and not a reference to some other object, then yes... 前提是(a)您的类及其超类可以在不泄漏内存或资源的情况下重新init并且(b)您知道您的类及其超类init都返回它们被传递的self ,而不是对其他某些对象的引用对象,然后是...

Otherwise things will go wrong. 否则会出错。 Consider your redefine method; 考虑您的redefine方法; in the body of this method self is just a local variable whose contents is initialized to point to some object. 在此方法的主体中, self只是一个局部变量,其内容被初始化为指向某个对象。 Changing the value in that local variable does not change the object it originally pointed at, or the value of any other variables which point to that object. 更改该局部变量中的值不会更改其最初指向的对象或指向该对象的任何其他变量的值。 Eg consider the variation: 例如考虑变化:

@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

Clearly this does not alter someQ , and your version may not either. 显然,这不会改变someQ ,您的版本也可能不会改变。 Your code will have the effect you wish if and only if you know init always returns the object it was passed - which is not guaranteed in Obj-C. 当且仅当您知道init始终返回传递了它的对象时,您的代码才会产生您希望的效果-Obj-C不保证这一点。

As long as init returns self , which it normally does, nothing will go wrong. 只要init返回self (通常会这样做),就不会出错。

But you probably want to split your initialization to some separate method, which you can call from both init and redefine . 但是您可能希望将初始化拆分为一些单独的方法,您可以从initredefine调用该方法。

You need to return your new object from -init , not simply assign a new value to self. 您需要从-init返回新对象,而不是简单地为self分配新值。 And you must remember to release the old self, since it was created with +alloc . 而且,您必须记住要释放旧的self,因为它是使用+alloc创建的。 Caveats aside though, returning a different object from -init is explicitly allowed. 除了警告,明确允许从-init返回不同的对象。 That's why you'll see newbies being corrected when they write something like this: 这就是为什么您会看到新手在编写如下内容时得到纠正:

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

This is an anti-pattern because -init is not required to return the same object it was called on. 这是一个反模式,因为-init 不需要返回它被称为在同一个对象。 That means the above can end up assigning foo to point to an object that's been released, instead of to the object that was initialized in its place. 这意味着以上内容最终可以将foo分配为指向已释放的对象,而不是指向已在其位置初始化的对象。 This is why you always see +alloc and `init chained together like so: 这就是为什么您总是看到+alloc`init像这样链接在一起的原因:

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

It's also why you need to reassign self when calling super's -init , because it may also have returned a different object. 这也是为什么在调用super的-init时需要重新分配self的原因,因为它可能还返回了另一个对象。

self = [super init];

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM