为什么我们使用[super dealloc]而不是[self dealloc]或[object dealloc]

时间:2011-07-05 18:36:03

标签: objective-c ios cocoa-touch cocoa

谈论的是Objective-c中的类和对象。 我无法理解[super dealloc]的概念。 我们有一些类说myClass,它继承自NSObject。它有一些方法,并从父类继承其他方法。所以我们这里也有dealloc方法。为什么我不能只使用[myInstance dealloc]? 我是否认为我们调用父类方法来杀死类的实例?为什么这么复杂?

这不是关于[myInstance发布]的讨论我对这个概念没问题。

7 个答案:

答案 0 :(得分:8)

已经有一些很好的答案,但我会更直接地回答这些问题:

  1. 为什么我们写[super dealloc]

    我们写它是因为那是实际销毁实例的东西。否则永远不会释放内存。

  2. 为什么我们不写[self dealloc]

    我们无法写出来,因为您应该明确调用dealloc的唯一地方是dealloc方法。在[self dealloc]内执行dealloc只会使方法调用本身,然后调用自身,调用自身,调用自身,并调用自身......。

  3. 为什么我们不写[myInstance dealloc]

    我认为myInstance只是另一个指向对象的方法中的变量的占位符,而您在问我们为什么不通过该变量调用dealloc。这是因为你不知道对象何时应该dealloc retainrelease的重点是让您不必跟踪对象何时被销毁。您只需正确保留和释放对象,并且当release被调用足够多次,表明该对象没有更多的所有者想要保留对它的引用时,它将自己调用dealloc

答案 1 :(得分:7)

您的问题实际上是一个更通用的问题,可以从dealloc问题中删除。

覆盖方法以及何时应致电super

有时,当您进行子类化时,您将覆盖现有方法。有时你想利用那个方便的时间来执行一些行为,有时你想阻止父母做某事并改变行为。

- (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 …
}

许多方法/类的文档(请参阅UIView和NSManagedObject)可能会说明您是否可以或不应该覆盖方法。好的文档会告诉你何时应该调用super。

在调用[super dealloc]时,您应该在释放资源后最后调用它。 (因为您可能引用的其他内存可能会被您的父类释放)。

另一个super的调用是在init方法中。如果你实现了一个init方法,你应该覆盖父方的“指定初始化方法”,你应该从你的方法中调用super。

@implementation CustomViewController

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

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

//…

此常见模式可防止任何人使用不正确的nib文件加载您的类。 (这可能是也可能不是,这是另一个问题。)

如果碰巧有其他初始化器,根据定义,它们应该调用它们的指定初始化器。因此,如果UIView要添加initWithNibName:方法,它可能会调用[self initWithNibName:name bundle:nil],然后将其“捕获”并重定向到您想要的初始化程序。

答案 2 :(得分:5)

调用-dealloc时,合同是它在类层次结构中向上运行,以确保正确处理每个父类使用的内存。 [self dealloc]会再次调用您的方法并为您提供无限循环。 [super dealloc]删除你的超类设置的任何内容 - 如果那个超类是NSObject,它还会释放对象占用的内存。

答案 3 :(得分:3)

你这样做:

@interface MyClass : SuperClass
@end

@implementation MyClass

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

@end

那是什么意思?假设你有一个MyClass的实例,它已经被释放/自动释放,直到它的保留计数降到0. Objective-C现在想要销毁实例。为了清理内容,Objective-C调用dealloc方法。

现在,被调用的是MyClass中定义的dealloc。但是你从其他一些类派生了这个类。这意味着这个超类也可能有清理的东西。所以你必须调用[super dealloc];,这意味着:按照SuperClass 中的定义执行dealloc

类似的概念适用于您的initinitFoo方法:在其中您执行类似self = [super init];的操作,以便超类可以进行初始化。

此外,您不应该直接致电dealloc!只有在清理对象的时候才能通过Objective-C调用它。

BTW,self表示:我的对象的当前实例,而super表示:我的对象的当前实例,但使用定义的方法由超类

答案 4 :(得分:1)

简而言之,它是初始化程序的补充。概念是初始化从inheiritance层次结构的顶部传播到底部以首先初始化所有父字段,并且释放从底部传播到顶部以首先清理所有子字段。在init方法中,您始终先致电[super init],然后在dealloc中始终致电[super dealloc]。有关[super dealloc]的更多信息,请查看this question

答案 5 :(得分:0)

不,你是对的。

父类(在您的示例中为NSObject)必须运行自己的指令。 这就是为什么在您编写发布说明之后,将dealloc发送到超类以完成此过程。

答案 6 :(得分:0)

[self dealloc]中使用-dealloc会导致无限递归。 -dealloc方法会继续调用自己。您无法在[object dealloc]中使用-dealloc,因为除了self之外,您不会,也不应该指向自己。你是正确的NSObject需要自己清理。一个班级创造的所有东西都负责清理。此外,[super dealloc]必须是-dealloc的最后一行。否则,您可能在该点之后没有分配的对象。

相关问题