我对 Obj-C 消息有一些疑问。
(1) 这是我的主要问题:如何确保一个类在混合或调用它之前具有其超类的实现?
如果我想使用目标类未实现但其超类实现的方法进行方法调配,如何确保该类在方法调配之前具有其超类的实现?
我知道当一条消息发送到一个没有实现它的对象时,Obj-C 运行时将首先查找它的继承层次结构以从它的超类中找到实现。如果有,Obj-C 会将其缓存在不同的调度表中并调用它。
我可以使用这个缓存的实现进行方法调配吗?如果可以,如何确保在方法调配或向该对象发送任何消息之前有一个缓存的实现?如果没有,如何向这个类添加一个真正的实现,它只会super
在方法调整之前调用 's 的实现?
例如,有这样的类层次结构:
@interface A : NSObject
- (void) helloWorld;
@end
@interface B : A
@end
@interface C : B
@end
@interface D : C
@end
@interface E : D
@end
和这样的实现:
@implemenation A
- (void) helloWorld{
NSLog(@"hello world from class A");
}
@end
@implemenation B
// did not override -helloWorld
@end
@implemenation C
- (void) helloWorld{
[super helloWorld];
NSLog(@"hello world from class C");
}
@end
@implemenation D
// did not override -helloWorld
@end
@implemenation E
// did not override -helloWorld
@end
我只想在运行时-helloWorld
与 Class完全交换(而不是添加)实现。D
如果这样的 swizzled 方法,这个技巧将在原始实现中添加一个额外的任务:
@implemenation D (AdditionalWorkForHelloWorld)
- (void) additionalWorkForHelloWorld{
[self additionalWorkForHelloWorld];
NSLog(@"hello every one!");
}
@end
因此,当我向 Class或 Class-helloWorld
的实例发送消息时,控制台将打印以下消息:D
E
-> hello world from class A
-> hello world from class C
-> hello every one!
有一天,在类D
实现-helloWorld
如下之后:
@implemenation D
- (void) helloWorld{
[super helloWorld];
NSLog(@"hello world from class D");
}
@end
并向 Class或 Class-helloWorld
的实例发送消息,控制台将打印以下消息:D
E
-> hello world from class A
-> hello world from class C
-> hello world from class D
-> hello every one!
这种方法交换将确保无论类D
实现-helloWorld
与否都会调用附加任务。
我问了一个关于如何使 C 函数调用对象的super
实现的问题,这似乎并不容易。Obj-C 是如何实现这种缓存机制来将消息转发到super
's implementation 的?
(2) Obj-C 如何处理super
关键字?在哪里super
?
在 Obj-C 消息中,前两个参数是隐藏的:self
和_cmd
. 您可以在 Obj-C 实现中使用它们。但在哪里super
?
a 是否super
等于self
'isa
指针?Obj-C 如何处理super
关键字?
每个 Obj-C 消息都将转换为objc_msgSend()
or objc_msgSend_stret()
。那么发送到的每条消息super
都会转换为objc_msgSendSuper()
andobjc_msgSendSuper_stret()
吗?
在前面提到的示例中,当我向-helloWorld
Class 发送消息并且E
Class不响应时,Obj-C 会将消息发送到 Class的实现。在 Class的 implementation 中,它调用了它的 implementation,但 Class没有实现它,所以将它转发给 Class 。D
E
C
C
super
B
A
在这种情况下,super
ClassC
应该是 Class B
,所以它实际上调用了 ClassB
的缓存实现,不是吗?我可以调整 ClassB
的缓存实现吗?