MST

星途 面试题库

面试题:Objective-C元类体系下self与super关键字的深度解析

深入探讨Objective-C的元类体系,说明self与super在元类体系下是如何进行消息传递和方法调度的。当在类方法中使用self和super时,其消息发送的具体流程是怎样的,这种机制对Objective-C的运行时特性有哪些重要影响?请结合具体代码示例和运行时原理进行详细分析。
11.5万 热度难度
编程语言Objective-C

知识考点

AI 面试

面试题答案

一键面试

1. Objective - C的元类体系

在Objective - C中,每个类(Class)都有一个关联的元类(meta - class)。元类用于存储类方法。类对象的isa指针指向其元类,而元类的isa指针指向根元类。根元类的isa指针指向自身。根类(如NSObject)的元类的父类是根类本身,其他元类的父类是其对应类的父类的元类。这种体系结构形成了一个复杂的继承层次,使得类方法也能像实例方法一样遵循继承规则。

2. self与super在元类体系下的消息传递和方法调度

  • self:当使用self发送消息时,运行时系统首先会在self的类(如果是类方法,就是元类)的方法列表中查找方法实现。如果找不到,就沿着继承链(元类的继承链)向上查找,直到找到方法实现或者到达根元类。
  • supersuper并不是一个指针,而是一个编译器指示符。当使用super发送消息时,编译器会改变消息查找的起始点。对于类方法,会从当前类的元类的父类的方法列表开始查找方法实现,然后沿着继承链向上查找,这与self从当前类(元类)开始查找不同。

3. 类方法中self和super消息发送的具体流程

代码示例

#import <Foundation/Foundation.h>

@interface ParentClass : NSObject
+ (void)classMethod;
@end

@implementation ParentClass
+ (void)classMethod {
    NSLog(@"ParentClass class method");
}
@end

@interface ChildClass : ParentClass
+ (void)classMethod;
@end

@implementation ChildClass
+ (void)classMethod {
    NSLog(@"ChildClass class method before self");
    [self classMethod];
    NSLog(@"ChildClass class method before super");
    [super classMethod];
    NSLog(@"ChildClass class method after super");
}
@end

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        [ChildClass classMethod];
    }
    return 0;
}

流程分析

  • [self classMethod]:在ChildClass的类方法classMethod中,当执行[self classMethod]时,运行时系统首先在ChildClass的元类的方法列表中查找classMethod。因为ChildClass元类中有该方法,所以会调用ChildClassclassMethod,形成递归调用。为了打破递归,ChildClassclassMethod实现中应该避免这种直接递归,实际应用中会有不同的业务逻辑。这里递归调用会一直执行ChildClass class method before self这行日志输出,直到栈溢出。在修正代码避免递归后,会执行到[super classMethod]
  • [super classMethod]:当执行[super classMethod]时,编译器会让运行时系统从ChildClass元类的父类(也就是ParentClass的元类)的方法列表中查找classMethod。找到后执行ParentClassclassMethod,输出ParentClass class method。执行完ParentClassclassMethod后,继续执行ChildClass类方法中[super classMethod]之后的代码,输出ChildClass class method after super

4. 这种机制对Objective - C运行时特性的重要影响

  • 动态绑定:通过元类体系和selfsuper的消息传递机制,Objective - C实现了动态绑定。在运行时才确定方法的实际调用,这使得程序更加灵活,比如可以在运行时替换类的实现等。
  • 继承与多态:元类体系和消息传递机制保证了类方法也能像实例方法一样遵循继承和多态规则。子类可以重写父类的类方法,并且通过super调用父类的类方法实现,增强了代码的复用性和扩展性。
  • 运行时的灵活性:这种机制使得Objective - C在运行时可以进行许多高级操作,如方法交换(method swizzling)。可以在运行时动态改变类的方法实现,无论是实例方法还是类方法,这在很多框架和库的实现中都有广泛应用,比如AOP(面向切面编程)的实现。