面试题答案
一键面试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首先在ChildClass
、ParentClass
的方法列表中查找,未找到后进入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
方法的变体实现,动态方法解析机制会正确处理,保证多态特性不受影响。