MST

星途 面试题库

面试题:深入剖析Objective-C动态方法解析与runtime其他机制的交互关系

Objective-C的动态方法解析并非孤立存在,它与runtime中的消息转发、类结构等其他机制紧密相连。请深入分析动态方法解析是如何与这些runtime机制相互协作和影响的,例如在复杂的继承体系和多态场景下,这些机制是如何共同确保对象方法调用的正确性和灵活性的,同时结合具体代码示例来说明。
22.5万 热度难度
编程语言Objective-C

知识考点

AI 面试

面试题答案

一键面试

1. 动态方法解析与runtime机制的协作关系

1.1 动态方法解析(Dynamic Method Resolution)

在Objective-C中,当向一个对象发送一条它无法识别的消息时,runtime会启动动态方法解析机制。runtime首先会尝试在类的方法列表中查找方法实现,如果未找到,会进入动态方法解析阶段。

1.2 与消息转发(Message Forwarding)的协作

  • 动态方法解析在前:动态方法解析是消息转发的第一个阶段。如果在动态方法解析阶段,类成功添加了对应的方法实现,那么消息转发就会停止,对象可以正常响应消息。例如:
#import <objc/runtime.h>

@interface MyClass : NSObject
@end

@implementation MyClass
+ (BOOL)resolveInstanceMethod:(SEL)sel {
    if (sel == @selector(missingMethod)) {
        class_addMethod(self, sel, (IMP)customMethodImplementation, "v@:");
        return YES;
    }
    return [super resolveInstanceMethod:sel];
}

void customMethodImplementation(id self, SEL _cmd) {
    NSLog(@"This is a dynamically added method");
}
@end
  • 消息转发后续阶段:如果动态方法解析未能处理消息,runtime会进入消息转发的后续阶段,即备用接收者(Fast Forwarding)和完整转发(Normal Forwarding)。

1.3 与类结构(Class Structure)的关系

  • 方法查找依赖类结构:runtime在进行方法查找(包括动态方法解析前的初始查找)时,依赖类的结构信息,如类的方法列表、父类指针等。在继承体系中,runtime会沿着继承链查找方法实现。例如:
@interface SuperClass : NSObject
- (void)commonMethod;
@end

@implementation SuperClass
- (void)commonMethod {
    NSLog(@"SuperClass's commonMethod");
}
@end

@interface SubClass : SuperClass
@end

@implementation SubClass
@end

当向SubClass的实例发送commonMethod消息时,runtime先在SubClass的方法列表中查找,未找到则沿着父类指针到SuperClass的方法列表中查找。

2. 在复杂继承体系和多态场景下的作用

2.1 复杂继承体系

在多层继承体系中,动态方法解析和消息转发机制共同确保方法调用的正确性。例如:

@interface GrandParentClass : NSObject
@end

@implementation GrandParentClass
+ (BOOL)resolveInstanceMethod:(SEL)sel {
    if (sel == @selector(missingMethodInGrandParent)) {
        class_addMethod(self, sel, (IMP)grandParentCustomMethodImplementation, "v@:");
        return YES;
    }
    return [super resolveInstanceMethod:sel];
}

void grandParentCustomMethodImplementation(id self, SEL _cmd) {
    NSLog(@"This is a dynamically added method in GrandParentClass");
}
@end

@interface ParentClass : GrandParentClass
@end

@implementation ParentClass
@end

@interface ChildClass : ParentClass
@end

@implementation ChildClass
@end

当向ChildClass的实例发送missingMethodInGrandParent消息时,runtime首先在ChildClassParentClass的方法列表中查找,未找到后进入GrandParentClass的动态方法解析阶段,若成功添加方法实现,则可正常响应消息。

2.2 多态场景

多态是指不同类的对象对同一消息做出不同响应。动态方法解析和消息转发机制在多态场景下保证了灵活性。例如:

@interface Animal : NSObject
- (void)makeSound;
@end

@implementation Animal
- (void)makeSound {
    NSLog(@"Animal makes a sound");
}
@end

@interface Dog : Animal
@end

@implementation Dog
- (void)makeSound {
    NSLog(@"Dog barks");
}
@end

@interface Cat : Animal
@end

@implementation Cat
- (void)makeSound {
    NSLog(@"Cat meows");
}
@end

在多态场景下,不同子类重写makeSound方法,runtime根据对象的实际类型调用相应的方法实现,即使在动态方法解析或消息转发过程中,也能确保正确的多态行为。例如,若某个子类在运行时动态添加了makeSound方法的变体实现,动态方法解析机制会正确处理,保证多态特性不受影响。