调用 [super init]
是否在类别中做与子类相同的事情?如果不是,有什么区别?
最佳答案
为了理解这一点,了解对象在运行时的存储方式可能很重要。有一个类对象1,它保存了所有的方法实现,另外,还有一个存储实例变量的结构。一个类的所有实例共享一个类对象。
当您调用实例上的方法时,编译器会将其转换为对 objc_msgSend
的调用;在类对象中查找方法实现,然后以实例作为参数运行。
对 super
的引用在编译时生效,不在运行时生效。当您编写 [super someMethod]
时,编译器会将其转换为对 objc_msgSendSuper
的调用而不是通常的 objc_msgSend
。这开始在父类(super class)的类对象中寻找方法实现,而不是实例的类对象。2
类别只是简单地向类对象添加方法;它与子类化几乎没有关系。
考虑到所有这些,如果您在类别内部引用 super
,它确实会做与在类内部相同的事情——在类对象上查找方法实现父类(super class),然后将该实例作为参数运行。
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 class)的实例 上调用。这就是方法和数据分离的用武之地。该方法仍然在编写 [super someMethod]
的同一个实例上被调用,即子类的一个实例,使用该实例的数据;它只是使用父类(super class)的方法实现。
因此对[super class]
的调用转到父类(super class)对象,找到名为class
的方法的实现,并在实例上调用它,将其转换为相当于 [self theSuperclassImplementationOfTheMethodNamedClass]
。由于该方法所做的只是返回调用它的实例的类,您不会得到父类(super class)的类,而是得到self
的类。因此,调用 class
是对这种现象的糟糕测试。
整个答案完全忽略了消息传递/方法调用的区别。这是 ObjC 的一个重要特性,但我认为它可能只会混淆本已尴尬的解释。
关于objective-c - 在类别中调用 super 与在子类中调用它一样吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6168058/