编译器中的类元类根源类

Posted 吴建明

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了编译器中的类元类根源类相关的知识,希望对你有一定的参考价值。

编译器中的类、元类、根源类
1. 源码
main.m

#import <Foundation/Foundation.h>

@interface YCFather : NSObject

@property (nonatomic, copy) NSString *name;

+ (void)clsSayHello1;

- (void)insSayHello1;

@end

@implementation YCFather

+ (void)clsSayHello1

- (void)insSayHello1

@end

@interface YCSon : YCFather

@property (nonatomic, copy) NSString *midName;

+ (void)clsSayHello2;

- (void)insSayHello2;

@end

@implementation YCSon

+ (void)clsSayHello2

- (void)insSayHello2

@end

int main(int argc, char * argv[])

return 0;


编译器中的类、元类、根源类
1. 源码
main.m
#import <Foundation/Foundation.h>

@interface YCFather : NSObject
@property (nonatomic, copy) NSString *name;
+ (void)clsSayHello1;
- (void)insSayHello1;
@end
@implementation YCFather
+ (void)clsSayHello1
- (void)insSayHello1
@end

@interface YCSon : YCFather
@property (nonatomic, copy) NSString *midName;
+ (void)clsSayHello2;
- (void)insSayHello2;
@end
@implementation YCSon
+ (void)clsSayHello2
- (void)insSayHello2
@end

int main(int argc, char * argv[])
return 0;

2. Clang -rewrite-objc
执行下面的代码,会输出一个 main.cpp 文件。
xcrun -sdk iphoneos clang -arch arm64 -w -rewrite-objc -fobjc-arc -mios-version-min=8.0.0 -fobjc-runtime=ios-8.0.0 main.m
注意:此处使用 clang -rewrite-objc 得到的c++代码只能做参考,与真实的代码还是会有一定出入,但逻辑基本一致。
1)类的基本结构
搜索 NSObject
#ifndef _REWRITER_typedef_NSObject
#define _REWRITER_typedef_NSObject
typedef struct objc_object NSObject;
typedef struct _objc_exc_NSObject;
#endif
struct NSObject_IMPL
__unsafe_unretained Class isa;
;
可以看到 NSObject 主要成员变量就是 Class ISA,下面再看看 YCFather 和 YCSon。
#ifndef _REWRITER_typedef_YCFather
#define _REWRITER_typedef_YCFather
typedef struct objc_object YCFather;
typedef struct _objc_exc_YCFather;
#endif
extern "C" unsigned long OBJC_IVAR_$_YCFather$_name;
struct YCFather_IMPL
struct NSObject_IMPL NSObject_IVARS; // 继承 NSObject_IMPL 的成员变量 isa
NSString *__strong _name; // 追加自己的 _name 成员变量
;
// @property (nonatomic, copy) NSString *name;
// + (void)clsSayHello1;
// - (void)insSayHello1;
/* @end */
// @implementation YCFather
// clsSayHello1 IMP
static void _C_YCFather_clsSayHello1(Class self, SEL _cmd)
// insSayHello1 IMP
static void _I_YCFather_insSayHello1(YCFather * self, SEL _cmd)
// name 属性的 get 方法
static NSString * _I_YCFather_name(YCFather * self, SEL _cmd) return (*(NSString *__strong *)((char *)self + OBJC_IVAR_$_YCFather$_name));
extern "C" __declspec(dllimport) void objc_setProperty (id, SEL, long, id, bool, bool);
// name 属性的 set 方法
static void _I_YCFather_setName_(YCFather * self, SEL _cmd, NSString *name) objc_setProperty (self, _cmd, __OFFSETOFIVAR__(struct YCFather, _name), (id)name, 0, 1);
// @end
#ifndef _REWRITER_typedef_YCSon
#define _REWRITER_typedef_YCSon
typedef struct objc_object YCSon;
typedef struct _objc_exc_YCSon;
#endif
extern "C" unsigned long OBJC_IVAR_$_YCSon$_midName;
struct YCSon_IMPL
struct YCFather_IMPL YCFather_IVARS; // 继承 YCFather_IMPL 的成员变量 isa 和 _name
NSString *__strong _midName; // 追加自己的 _midName 成员变量
;
// @property (nonatomic, copy) NSString *midName;
// + (void)clsSayHello2;
// - (void)insSayHello2;
/* @end */
// @implementation YCSon
// clsSayHello2 IMP
static void _C_YCSon_clsSayHello2(Class self, SEL _cmd)
// insSayHello2 IMP
static void _I_YCSon_insSayHello2(YCSon * self, SEL _cmd)
// midName 属性的 get 方法
static NSString * _I_YCSon_midName(YCSon * self, SEL _cmd) return (*(NSString *__strong *)((char *)self + OBJC_IVAR_$_YCSon$_midName));
// midName 属性的 set 方法
static void _I_YCSon_setMidName_(YCSon * self, SEL _cmd, NSString *midName) objc_setProperty (self, _cmd, __OFFSETOFIVAR__(struct YCSon, _midName), (id)midName, 0, 1);
// @end
2. 类中的信息
YCFather 和 YCSon 的分析类似,这里以 YCFather 为例进行分析。成员变量列表 OBJC$_INSTANCE_VARIABLES_YCFather。
static struct /*_ivar_list_t*/
unsigned int entsize; // sizeof(struct _prop_t)
unsigned int count;
struct _ivar_t ivar_list[1];
_OBJC_$_INSTANCE_VARIABLES_YCFather __attribute__ ((used, section ("__DATA,__objc_const"))) =
sizeof(_ivar_t),
// 只有一个成员变量
(unsigned long int *)&OBJC_IVAR_$_YCFather$_name, "_name", "@\\"NSString\\"", 3, 8 // 成员变量_name
;
实例方法列表 OBJC$_INSTANCE_METHODS_YCFather
static struct /*_method_list_t*/
unsigned int entsize; // sizeof(struct _objc_method)
unsigned int method_count;
struct _objc_method method_list[5];
_OBJC_$_INSTANCE_METHODS_YCFather __attribute__ ((used, section ("__DATA,__objc_const"))) =
sizeof(_objc_method),
5, // 有5个实例方法,SEL、Encode、IMP
(struct objc_selector *)"insSayHello1", "v16@0:8", (void *)_I_YCFather_insSayHello1,
(struct objc_selector *)"name", "@16@0:8", (void *)_I_YCFather_name,
(struct objc_selector *)"setName:", "v24@0:8@16", (void *)_I_YCFather_setName_,
(struct objc_selector *)"name", "@16@0:8", (void *)_I_YCFather_name,
(struct objc_selector *)"setName:", "v24@0:8@16", (void *)_I_YCFather_setName_
;
类方法列表 OBJC$_CLASS_METHODS_YCFather。
static struct /*_method_list_t*/
unsigned int entsize; // sizeof(struct _objc_method)
unsigned int method_count;
struct _objc_method method_list[1];
_OBJC_$_CLASS_METHODS_YCFather __attribute__ ((used, section ("__DATA,__objc_const"))) =
sizeof(_objc_method),
1, // 有1个类方法,SEL、Encode、IMP
(struct objc_selector *)"clsSayHello1", "v16@0:8", (void *)_C_YCFather_clsSayHello1
;
属性方法列表 OBJC$_PROP_LIST_YCFather。
static struct /*_prop_list_t*/
unsigned int entsize; // sizeof(struct _prop_t)
unsigned int count_of_properties;
struct _prop_t prop_list[1];
_OBJC_$_PROP_LIST_YCFather __attribute__ ((used, section ("__DATA,__objc_const"))) =
sizeof(_prop_t),
1, // 有1个属性
"name","T@\\"NSString\\",C,N,V_name"
;
元类对象 RO 的初始化 OBJCMETACLASS_RO_$_YCFather。
常见重点1:类方法存储在元类 (注意static,这些信息只存在一份)。
static struct _class_ro_t _OBJC_METACLASS_RO_$_YCFather __attribute__ ((used, section ("__DATA,__objc_const"))) =
1, sizeof(struct _class_t), sizeof(struct _class_t),
0,
"YCFather",
(const struct _method_list_t *)&_OBJC_$_CLASS_METHODS_YCFather, // YCFather 的类方法存储在元类
0,
0,
0,
0,
;
类对象 RO 的初始化 OBJCCLASS_RO_$_YCFather。
常见重点2:实例方法存储在类 (注意static,这些信息只存在一份)
static struct _class_ro_t _OBJC_CLASS_RO_$_YCFather __attribute__ ((used, section ("__DATA,__objc_const"))) =
0, __OFFSETOFIVAR__(struct YCFather, _name), sizeof(struct YCFather_IMPL),
0,
"YCFather",
(const struct _method_list_t *)&_OBJC_$_INSTANCE_METHODS_YCFather, // 方法列表
0,
(const struct _ivar_list_t *)&_OBJC_$_INSTANCE_VARIABLES_YCFather, // 成员变量列表
0,
(const struct _prop_list_t *)&_OBJC_$_PROP_LIST_YCFather, // 属性列表
;
元类 OBJC_METACLASS__YCFather∗∗、类∗∗OBJC_CLASS__YCFather**、类 **OBJC_CLASS__YCFather∗∗、类∗∗OBJC_CLASS__YCFather 的初始化。
extern "C" __declspec(dllimport) struct _class_t OBJC_METACLASS_$_NSObject;
// 元类的初始化
extern "C" __declspec(dllexport) struct _class_t OBJC_METACLASS_$_YCFather __attribute__ ((used, section ("__DATA,__objc_data"))) =
0, // &OBJC_METACLASS_$_NSObject,
0, // &OBJC_METACLASS_$_NSObject,
0, // (void *)&_objc_empty_cache,
0, // unused, was (void *)&_objc_empty_vtable,
&_OBJC_METACLASS_RO_$_YCFather,
;
extern "C" __declspec(dllimport) struct _class_t OBJC_CLASS_$_NSObject;
// 类的初始化
extern "C" __declspec(dllexport) struct _class_t OBJC_CLASS_$_YCFather __attribute__ ((used, section ("__DATA,__objc_data"))) =
0, // &OBJC_METACLASS_$_YCFather,
0, // &OBJC_CLASS_$_NSObject,
0, // (void *)&_objc_empty_cache,
0, // unused, was (void *)&_objc_empty_vtable,
&_OBJC_CLASS_RO_$_YCFather,
;
3. 元类与类的关系绑定
常见重点3:类、元类、根源类的关系
static void OBJC_CLASS_SETUP_$_YCFather(void )
OBJC_METACLASS_$_YCFather.isa = &OBJC_METACLASS_$_NSObject; // YCFather元类的 isa 为 NSObject元类(根元类)
OBJC_METACLASS_$_YCFather.superclass = &OBJC_METACLASS_$_NSObject; // YCFather元类的 superclass 为 NSObject元类
OBJC_METACLASS_$_YCFather.cache = &_objc_empty_cache;
OBJC_CLASS_$_YCFather.isa = &OBJC_METACLASS_$_YCFather; // YCFather类的 isa 为 YCFather元类
OBJC_CLASS_$_YCFather.superclass = &OBJC_CLASS_$_NSObject; // YCFather类的 superclass 为 NSObject类
OBJC_CLASS_$_YCFather.cache = &_objc_empty_cache;

// 这里特意补上 YCSon 的关系绑定
static void OBJC_CLASS_SETUP_$_YCSon(void )
OBJC_METACLASS_$_YCSon.isa = &OBJC_METACLASS_$_NSObject; // YCSon元类的 isa 为 NSObject元类(根元类)
OBJC_METACLASS_$_YCSon.superclass = &OBJC_METACLASS_$_YCFather; // YCSon元类的 superclass 为 YCSon元类的
OBJC_METACLASS_$_YCSon.cache = &_objc_empty_cache;
OBJC_CLASS_$_YCSon.isa = &OBJC_METACLASS_$_YCSon; // YCSon类的 isa 为 YCSon元类
OBJC_CLASS_$_YCSon.superclass = &OBJC_CLASS_$_YCFather; // YCSon类的 superclass 为 YCFather类
OBJC_CLASS_$_YCSon.cache = &_objc_empty_cache;

这里比较可惜的是,无法直观地看到 OBJC_METACLASS_$_NSObject 中的结构,但可以通过运行时或源码分析,已经得到了下面这张经典的图片了。根据上面的代码分析,也可以直观的验证如图5.20所示的大部分关系。

 图1 类、元类、根源类的关系图

 

参考文献链接

https://mp.weixin.qq.com/s/r2O4gCDMY44YGmWYMMfFjQ
https://juejin.cn/post/6874391520334577677#heading-8

1104课堂小结

exec

exec是什么

exec 是一个python的内置模块

exec的作用

可以把‘字符串形式’的python代码,添加到全局或者局部名称空间中

exec的使用方法

  1. 参数一:字符串形式的python代码
  2. 参数二:全局名称空间字典
  3. 参数三:局部名称空间字典

调用exec()

元类

什么是元类

元类就是类的类,Chinese类的类是type,type是所有类的类,所以type就是一个元类

元类的作用

元类可以帮我们控制类的创建和调用

怎么自定义创建元类

  1. 自定义一个元类,继承type,派生出自己的属性和方法

  2. 给需要使用的类,通过metaclass指定自定义好的元类

    如:class chinese(mataclass=‘自定义的元类‘)

优酷架构

ATM架构

优点:数据可以跨平台

缺点:不能存对象,也不能直接获取对象

? 不能通过“对象.属性”的方式存取值

? 存储速度比pickle慢

选课系统架构

优点:可以通过“对象.属性”的方式存取值

? 能存对象,也能直接获取对象

? 如:pickle

缺点: 不能跨平台

优酷架构

  • 数据层
    • 存储对象 ---->dict ----> json ----> Mysql
    • MySQL ----> Json ----> dict ----> 获取对象

ORM

对象关系映射----> 映射到数据库MYSQL中的数据表

类名 ----> 表名

对象 ----> 一条记录

对象.属性 ----> 字段

模拟Django的ORM ,为了将数据库的增删改查全部封装成一个个的方式,比如save,delete,update,select

ORM三个问题

  1. 解决代码冗余问题

    解决方式:继承一个父类,父类中定义一个__init__

  2. 无法预测每一张表中的字段是什么,无法通过父类的__init__解决问题

    解决方法:通过继承字典内部的__init__,可以接受任意个数的关键字参数

  3. 继承字典的类实例化的对象,无法通过“对象.属性”的方式存取值

    解决方法:通过__setattr____getattr__来实现,让字典对象与普通对象一模一样,并且具备字典原有的特性

以上是关于编译器中的类元类根源类的主要内容,如果未能解决你的问题,请参考以下文章

python元类深入解析

iOS-isa指针;objc实例对象类元类根类根元类

python 元类

面向对象之元类

python 吐血总结面向对象元类

python 吐血总结面向对象元类