0%

OC class、superClass方法

测试代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
- (void)test_class_superClass {
Person *per = [[Person alloc] init];
Class cls = [per class]; //Person
Class cls1 = [per superclass]; //Animal
Class cls2 = Person.self; //Person
Class cls3 = [Person class]; //Person
Class cls4 = [Person superclass]; //Animal
Class cls5 = object_getClass(per); //Person
Class cls6 = class_getSuperclass([Person class]); //Animal
Class cls7 = object_getClass([Person class]); //Person的元类
Class cls8 = class_getSuperclass(cls7); //Person元类的父类
Class cls9 = [cls7 superclass]; //Person元类的父类 等于cls8
}

获取对象的类

获取一个对象(实例对象或类对象)的类的核心方法就是object_getClass,实现:

1
2
3
4
5
Class object_getClass(id obj)
{
if (obj) return obj->getIsa();
else return Nil;
}

其实就是获取objc_object结构体里的isa字段的值。因此如果传入的是类对象,那么返回的将是类对象的类即元类。

实例方法class的实现就是调用object_getClass:

1
2
3
- (Class)class {
return object_getClass(self);
}

但是类方法class,并不是返回类对象的类,而是直接返回的自己。

1
2
3
4
5
6
7
+ (Class)class {
return self;
}

+ (id)self {
return (id)self;
}

所以如果想要获取类的类则必须使用object_getClass。

获取对象的父类

核心方法是getSuperclass,其实就是objc_class结构体里的superclass的值。

实例方法superclass:先获取到它的类再调用getSuperclass。

1
2
3
- (Class)superclass {
return [self class]->getSuperclass();
}

类方法superclass:返回类对象结构体里的superclass的值。

1
2
3
+ (Class)superclass {
return self->getSuperclass();
}

class_getSuperclass传入的参数需要是一个类对象,他的功能和类方法superclass一致。

1
2
3
4
5
Class class_getSuperclass(Class cls)
{
if (!cls) return nil;
return cls->getSuperclass();
}

self和super

测试代码:

1
2
3
4
5
6
7
8
9
10
11
12
@implementation Person

- (instancetype)init {
self = [super init];
if (self) {
NSLog(@"[self class]:%@", NSStringFromClass([self class]));
NSLog(@"[super class]:%@", NSStringFromClass([super class]));
NSLog(@"[self superclass]:%@", NSStringFromClass([self superclass]));
NSLog(@"[super superclass]:%@", NSStringFromClass([super superclass]));
}
return self;
}

输出:

1
2
3
4
2023-05-07 13:03:59.923896+0800 runtime方法使用Demo[18358:7221193] [self class]:Person
2023-05-07 13:03:59.924017+0800 runtime方法使用Demo[18358:7221193] [super class]:Person
2023-05-07 13:03:59.924140+0800 runtime方法使用Demo[18358:7221193] [self superclass]:Animal
2023-05-07 13:03:59.924237+0800 runtime方法使用Demo[18358:7221193] [super superclass]:Animal

从-class方法的实现:

1
2
3
- (Class)class {
return object_getClass(self);
}

可以看出,object_getClass的参数就是对象本身,所以不管是[self class]还是[super class],传入的参数都是Person对象而不是Animal对象。所以二者的结果是一样的。

super本质上是一个编译指示器, 它并不是一个指针, 它仅仅是表示调用父类的方法,但是调用者仍然是当前对象,跟父类没有关系.也就是说上面的例子不管调用[self class]还是[super class],接受消息的对象都是当前Person这个对象.

使用self调用方法时,会从当前类的方法列表中开始找,如果没有,就从父类中再找;而当使用super时,则从父类的方法列表中开始找.然后调用父类的这个方法,消息接收者对象还是当前这个对象。

内部实现

相关方法声明:

1
2
3
4
5
6
7
NSObject协议:实例方法
@property (readonly) Class superclass;
- (Class)class OBJC_SWIFT_UNAVAILABLE("use 'type(of: anObject)' instead");

NSObject类:类方法
+ (Class)superclass;
+ (Class)class OBJC_SWIFT_UNAVAILABLE("use 'aClass.self' instead");

关于+class说明:

Refer to a class only by its name when it is the receiver of a message. In all other cases, the class object must be obtained through this or a similar method. For example, here SomeClass is passed as an argument to the isKindOfClass: method (declared in the NSObject protocol):BOOL test = [self isKindOfClass:[SomeClass class]];

只有类作为消息的接收者的情况才可以直接使用类名代表该类。所有其他需要类的地方都需要通过调用类似class的方法来获取类对象。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
+ (id)self {
return (id)self;
}

- (id)self {
return self;
}

+ (Class)class {
return self;
}

- (Class)class {
return object_getClass(self);
}

+ (Class)superclass {
return self->getSuperclass();
}

- (Class)superclass {
return [self class]->getSuperclass();
}


/***********************************************************************
* object_getClass.
* Locking: None. If you add locking, tell gdb (rdar://7516456).
**********************************************************************/
Class object_getClass(id obj)
{
if (obj) return obj->getIsa();
else return Nil;
}

Class class_getSuperclass(Class cls)
{
if (!cls) return nil;
return cls->getSuperclass();
}

superClass

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
struct objc_class : objc_object {
objc_class(const objc_class&) = delete;
objc_class(objc_class&&) = delete;
void operator=(const objc_class&) = delete;
void operator=(objc_class&&) = delete;
// Class ISA;
Class superclass;
cache_t cache; // formerly cache pointer and vtable
class_data_bits_t bits; // class_rw_t * plus custom rr/alloc flags

Class getSuperclass() const {
return superclass;
}
...
};

struct objc_object {
private:
isa_t isa;

public:

// ISA() assumes this is NOT a tagged pointer object
Class ISA(bool authenticated = false);

// rawISA() assumes this is NOT a tagged pointer object or a non pointer ISA
Class rawISA();

// getIsa() allows this to be a tagged pointer object
Class getIsa();

uintptr_t isaBits() const;
...
}
觉得文章有帮助可以打赏一下哦!