调用[super init]
在类别中作为子类执行相同的操作吗?如果没有,有什么区别?
答案 0 :(得分:14)
为了理解这一点,理解运行时对象的存储方式可能很重要。有一个类对象 1 ,它包含所有方法实现,另外,还有一个结构,其中包含实例变量的存储。类的所有实例共享一个类对象。
当您在实例上调用方法时,编译器会将其转换为对objc_msgSend
的调用;在类对象中查找方法实现,然后以实例作为参数运行。
对super
的引用在编译时生效,不运行时。当您编写[super someMethod]
时,编译器会将其转换为对objc_msgSendSuper
的调用,而不是通常的objc_msgSend
。这开始在超类的类对象中寻找方法实现,而不是实例的类对象。 2
类别只是向类对象添加方法;它与子类化很少或没有关系。
考虑到所有这些,如果你在一个类别中引用super
,它确实做了与它在类中相同的事情 - 方法实现被查找在<的类对象上em> superclass ,然后以该实例作为参数运行。
Itai的帖子更直接地回答了这个问题,但在代码中:
@interface Sooper : NSObject {}
- (void) meth;
@end
@interface Sooper ()
- (void) catMeth;
@end
@interface Subb : Sooper {}
- (void) subbMeth;
@end
@interface Subb ()
- (void) catSubbMeth;
@end
@implementation Sooper
- (void) meth {
[super doIt]; // Looks up doIt in NSObject class object
}
- (void) catMeth {
[super doIt]; // Looks up doIt in NSObject class object
}
@end
@implementation Subb
- (void) subbMeth {
[super doIt]; // Looks up doIt in Sooper class object
}
- (void) catSubbMeth {
[super doIt]; // Looks up doIt in Sooper class object
}
@end
1 请参阅Greg Parker的写作[objc explain]: Classes and meta-classes
2 需要注意的一件重要事情是,该方法不会在超类的实例上调用。这就是方法和数据分离的地方。该方法仍然在使用该实例的数据写入[super someMethod]
的同一实例上调用,即子类的实例;它只是使用超类的方法实现。
因此,对[super class]
的调用转到超类对象,找到名为class
的方法的实现,并在实例上调用它,将其转换为等效的[self theSuperclassImplementationOfTheMethodNamedClass]
。由于所有方法都返回实例的类,它被称为,你没有得到超类的类,你得到了self
的类。因此,调用class
对这种现象的测试很差。
这整个答案完全忽略了消息传递/方法调用的区别。这是ObjC的一个重要特征,但我认为这可能只是一个已经很尴尬的解释。
答案 1 :(得分:8)
NSObject
=&gt; MyObject
=&gt; MySubclass
,并说明MyObject
上有一个名为MyCategory
的类别。
现在,来自MyCategory
的呼叫类似于从MyObject
拨打电话,因此super
指向NSObject
,并且呼叫[super init]
会调用NSObject
}的-init
方法。但是,从子类调用super
指向MyObject
,因此使用super
进行初始化会调用MyObject
的{{1}}方法,除非它不是被覆盖的行为与-init
的行为不同。
这两种行为是不同的,所以在使用类别初始化时要小心;类别不是子类,而是当前类的添加。
答案 2 :(得分:2)
鉴于以下示例,super
将调用UIView
init(不是UINavigationBar
init方法)
@implementation UINavigationBar (ShadowBar)
- (void)drawRect:(CGRect)rect {
//draw the shadow ui nav bar
[super init];
}
@end
如果您将其子类化,[super init]
将调用UINavigationBar
init方法。
所以,是的,如果你将在UINavigationBar
init中做更多的事情(额外来自UIView),他们会做不同的事情。
答案 3 :(得分:0)
编辑:以下内容建立在一个有缺陷的前提下,请看看乔希的答案。
不删除,仍然是一个有趣的参考,可能会让你误入歧途。
他们是一回事...没有引用我们可能已经提到的任何外部讨论我应该......并且#34;用学术答案回答学术问题&#34;
@implementation categoryTestViewController (ShadowBar)
- (void)viewDidAppear:(BOOL)animated {
//draw the shadow ui nav bar
NSLog(@"super's class = %@, self's class %@",[super class],[self class]);
if ([self class] == [super class]) {
NSLog(@"yeah they are the same");
}
}
@end
输出:
2011-05-29 08:06:16.198 categoryTest[9833:207] super's class = categoryTestViewController, self's class categoryTestViewController
2011-05-29 08:06:16.201 categoryTest[9833:207] yeah they are the same
并且调用[super viewDidAppear:]将导致不调用任何东西......不是循环,所以我不知道它在那里做了什么。