开发者

Why do we use [super dealloc] and not [self dealloc] or [object dealloc]

开发者 https://www.devze.com 2023-03-17 17:15 出处:网络
The talk is about classes and objects in Objective-c. I can\'t get my head around the concept of [super dealloc].

The talk is about classes and objects in Objective-c. I can't get my head around the concept of [super dealloc]. We have some class say myClass, that inherits from NSObject. It has some methods and inherits other methods from parent class. So we have dealloc method here too. Why can't I just use [myInstance dealloc]? Am I right to think that we call parent class method to kill the instance of the class? Why so complicated?

T开发者_Go百科hat's not discussion about [myInstance release] I'm ok with that concept.


There are already some good answers, but I'll answer the questions a little more directly:

  1. Why do we write [super dealloc]?

    We write it because that's what actually destroys the instance. Otherwise the memory would never be freed.

  2. Why don't we write [self dealloc]?

    We can't write that because the only place where you should ever explicitly call dealloc is inside a dealloc method. Doing [self dealloc] inside dealloc would just make the method call itself, which would then call itself, and call itself, and call itself, and call itself….

  3. Why don't we write [myInstance dealloc]?

    I assume myInstance is just a placeholder for a variable in another method that points to an object, and you're asking why we don't just call dealloc through that variable. This is because you don't know when the object should dealloc. The whole point of retain and release is to free you from having to keep track of when an object is ready to be destroyed. You just retain and release the object properly, and when release has been called enough times, signaling that the object has no more owners who want to keep a reference to it, it will call dealloc on itself.


Your question is actually a more generic question that can be removed from the dealloc issue.

Overriding methods and when you should call super.

Sometimes when you are subclassing you override an existing method. Sometimes you want to use that convenient time to perform some behavior, sometimes you want to prevent the parent from doing something and change behavior.

- (void)methodOne {
  // don't let silly parent class do method one stuff

  // do my stuff …
}

- (void)methodTwo {
  // let parent perform his behavior first
  [super methodTwo];

  // do my stuff …
}

- (void)methodThree {
  // do my stuff …

  // let parent do his stuff after I have
  [super methodThree];
}

- (void)methodFour {
  // it's not common, but you might want to split your stuff with a call to
  // super - this usually involves knowledge of what super is up to

  // do some stuff …
  [super methodFour];
  // do my stuff …
}

The documentation for many methods/classes (see UIView and NSManagedObject) might say whether you can or should or shouldn't override methods. Good documentation will tell you when you should invoke super.

When invoking [super dealloc] you should invoke it last, after you have released the resources you have a hold on. (because it's likely that other memory you might reference will be released by your parent class).

Another oft invocation of super is in init methods. If you implement an init method, you should override the parent's "designated initializer", and you should call super from yours.

@implementation CustomViewController

- (id)init {
  return [super initWithNibName:@"CustomView" bundle:nil];
}

- (id)initWithNibName:(NSString *)name bundle:(NSBundle *)bundle {
  return [self init];
}

//…

This common pattern prevents anyone from loading your class with the incorrect nib file. (This may or may not be desired, that's another issue.)

If there happened to be other initializers, by definition they should invoke their designated initializer. So if UIView were to add a initWithNibName: method, it would likely invoke [self initWithNibName:name bundle:nil] which would then be "caught" and redirected to your intended initializer.


When -dealloc is called, the contract is that it works its way up the class hierarchy to ensure the memory used by every parent class is disposed of correctly. [self dealloc] would call your method again and give you an infinite loop. [super dealloc] tears down whatever your superclass set up--and if that superclass is NSObject, it also frees the memory the object occupies.


You do it like this:

@interface MyClass : SuperClass
@end

@implementation MyClass

- (void)dealloc
{
    // Release stuff allocated in MyClass
    [super dealloc];
}

@end

So what does it mean ? Suppose you've got an instance of MyClass and it has been released/autoreleased until its retain count drops to 0. Objective-C now want to destroy the instance. To clean up stuff, Objective-C calls dealloc method.

Now, what gets called is the dealloc as defined in MyClass. But you have derived the class from some other class. And that means that this superclass may have stuff to clean up as well. So you have to call [super dealloc]; which means: execute the dealloc as defined in SuperClass.

A similar concept applies to your init or initFoo methods: in it you do something like self = [super init]; so the superclass can do its initializing.

Also, you should never call dealloc directly ! It is meant to be called by Objective-C only when it's time to clean up the object.

BTW, self means: the current instance of my object, while super means: the current instance of my object, but use the methods as defined by the superclass.


In short, it's the complement of the initializer. The concept is that the initialization propagates from the top to the bottom of the inheiritance hierarchy to initialize all parent fields first and that the deallocation propagates from the bottom to the top to clean up all the child fields first. In your init method, you always call [super init] first and in dealloc you always call [super dealloc] last. For a bit more info on [super dealloc], check out this question


No you are right.

The parent class (NSObject in your example) has to run its own instructions. That's why just after you wrote your release instructions, you send dealloc to the superclass in order to complete the process.


Using [self dealloc] in -dealloc would result in infinite recursion. The -dealloc method would just keep calling itself. You can't use [object dealloc] in -dealloc because you don't, and shouldn't, have a pointer to yourself aside from self. You are correct that NSObject needs to do its own cleaning up. Everything a class creates it is responsible for cleaning up. Also, [super dealloc] must be the last line of -dealloc. Otherwise you may not have an allocated object after that point.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号