在类别中调用super是否与在子类中调用super相同? [英] Is calling super in a category the same as calling it in a subclass?

查看:77
本文介绍了在类别中调用super是否与在子类中调用super相同?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在子类别中调用[super init]会做相同的事情吗?如果没有,有什么区别?

Does calling [super init] do the same thing in a category as a subclass? If not, what's the difference?

推荐答案

为了理解这一点,了解在运行时存储对象的方式可能很重要.有一个类对象 1 ,其中包含所有方法的实现,并且单独地有一个结构,用于存储实例变量.一个类的所有实例共享一个类对象.

In order to understand this, it's probably important to understand the way an object is stored during runtime. There is a class object1, which holds all the method implementations, and separately, there is a structure with the storage for the instance's variables. All instances of a class share the one class object.

在实例上调用方法时,编译器会将其转换为对

When you call a method on an instance, the compiler turns that into a call to objc_msgSend; the method implementation is looked up in the class object, and then run with the instance as an argument.

super的引用在编译时生效,而不在运行时生效.当您编写[super someMethod]时,编译器会将其转换为对

A reference to super takes effect at compile time, not run time. When you write [super someMethod], the compiler turns that into a call to objc_msgSendSuper instead of the usual objc_msgSend. This starts looking for the method implementation in the superclass's class object, rather than the instance's class object.2

一个类别只是向类对象添加方法;它与子类化几乎没有关系.

A category simply adds methods to the class object; it has little or no relation to subclassing.

鉴于所有这些,如果您在类别内部引用super,它的确实现了与类内部相同的功能-方法实现是在的类对象上查找的超类,然后将该实例作为参数运行.

Given all that, if you refer to super inside of a category, it does indeed do the same thing that it would inside of a class -- the method implementation is looked up on the class object of the superclass, and then run with that instance as an argument.

Itai的帖子更直接地回答了这个问题,但是使用了代码:

Itai's post answers the question more directly, but in code:

@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解释]:类和元类


1 See Greg Parker's writeup [objc explain]: Classes and meta-classes

2 需要注意的一件事是,该方法不会在超类的 instance 上调用.这是将方法和数据分开的地方.仍然在写[super someMethod]的同一实例(即子类的实例)上使用该实例的数据调用该方法.它仅使用方法的超类的实现.

2One important thing to note is that the method doesn't get called on an instance of the superclass. This is where that separation of methods and data comes in. The method still gets called on the same instance in which [super someMethod] was written, i.e., an instance of the subclass, using that instance's data; it just uses the superclass's implementation of the method.

因此,对[super class]的调用转到超类对象,找到名为class的方法的实现,并在实例上对其进行调用,将其转换为与[self theSuperclassImplementationOfTheMethodNamedClass]等效的方法.由于该方法所做的只是返回实例被调用的实例的类,因此您不会获得超类的类,而会获得self的类.因此,调用class对该现象的测试不佳.

So a call to [super class] goes to the superclass object, finds the implementation of the method named class, and calls it on the instance, transforming it into the equivalent of [self theSuperclassImplementationOfTheMethodNamedClass]. Since all that method does is return the class of the instance on which it was called, you don't get the superclass's class, you get the class of self. Due to that, calling class is kind of a poor test of this phenomenon.

整个答案完全忽略了消息传递/方法调用的区别.这是ObjC的重要功能,但我认为这可能只会使原本笨拙的解释变得混乱.

这篇关于在类别中调用super是否与在子类中调用super相同?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆