super01
打印结果分别是什么?
@interface Student : Person
@end
- (instancetype)init
{
self = [super init];
if (self) {
NSLog(@"class = %@", [self class]);//Student
NSLog(@"class = %@", [self superclass]);//Person
NSLog(@"class = %@", [super class]);//Student
NSLog(@"class = %@", [super superclass]);//Person
}
return self;
}
super02
我想要了解原因,就要了解super做了什么事情
[super class];底层调用了
objc_msgSendSuper(arg, @selector(eat))
这里的arg是一个封装了接受者receiver和接受者父类super_classd的结构体
虽然我们是通过super调用的方法,但是消息的就收者依然是student对象,传入的父类的作用,就是从父类开始搜索方法,因为如果不写的话,他会先从自己的类开始搜索。
class的底层的大概实现就是object_getClass(),就是返还接受者的类型,所以返值是由就收者决定的
super面试题
01
print为什么调用成功?为什么打印为的self.name会变成其他
id p = [Person class];
void *obj = &p;
[(__bridge id)obj test];
02
print为什么调用成功
说明左边的对象他也有,isa这个指针。我们平时调用方法其实就是根据实例对象的isa指针指到类对象,这里isa指针的地址,其实就是实例对象的地址,因为在内存中他是实例对象结构题第一个成员,而他只想向的地址就是我们的类对象,这里他是模拟了这个关系,用p带表示isa,obj模拟实例对象,所以是可以调用成功的,
03
为什么打印别的内容
因为我们以前调用的方法打印,他也就是找到我们isa指向的类类对象,跳过前面isa的8个字节,找后面的8个字节的内容。
结构体的成员,越往后越高,栈中分配的空间越往后越低。所以,他才回往上面寻找高地址的8个字节
NSString *school = @"ocean";
NSString *test = @"luoge";
id p = [Person class];
void *obj = &p;
[(__bridge id)obj test];
//打印 This is a test methodluoge--ocean
04
为什么会打印UIViewController是因为调用[super viewDidload]的时候,需要创建一个包含自己和父类的一个结构体,这个结构体是一个局部变量,这个就导致了打印出的是UIViewController,
struct aab {
self,
[UIViewConller class];
}
04
其实我们平时调用的objc_msgSendSuper转成的底层是objc_msgSendSuper2
id p = [Person class];
void *obj = &p;
[(__bridge id)obj test];
lldb打印
p/x obj
(Person *) $0 = 0x00007ffee8dd88c8
x/4g $0
0x7ffee8dd88c8: 0x0000000106e26f78 0x00007f99ccf07400
0x7ffee8dd88d8: 0x0000000106e26eb0 0x00007fff51e5f73c
p (Class)0x0000000106e26f78
(Class) $1 = Person
p (Class)0x0000000106e26eb0
(Class) $3 = ViewController
po 0x00007f99ccf07400
<ViewController: 0x7f99ccf07400>
网友评论