對于一門編程語言而言,當(dāng)初學(xué)者掌握了其基本語法和標(biāo)準(zhǔn)庫的使用以后椅亚,如果能夠繼續(xù)了解該語言的核心思想與底層實現(xiàn)限番,則會漸入佳境,窺探語言實現(xiàn)的本質(zhì)技術(shù)呀舔,能夠為以后的性能優(yōu)化以及規(guī)避技術(shù)陷阱等復(fù)雜工作提供思路弥虐。
了解Objective-C語言的面向?qū)ο蟮谋举|(zhì),有益于程序員更加深刻理解該語言是如何實踐OOP思想媚赖,并使得在構(gòu)建面向?qū)ο蟪绦虻臅r候更加游刃有余霜瘪。
背景知識
Objective-C是C語言的超集,也就是說惧磺,C語言的語法全部被Objective-C兼容颖对,而面向?qū)ο蟮奶匦詣t是建立在C語言的基礎(chǔ)之上,當(dāng)熟悉過C語言的指針磨隘、內(nèi)存管理缤底、自定義數(shù)據(jù)-結(jié)構(gòu)體等一系列知識以后顾患,對于Objective-C的面向?qū)ο髮崿F(xiàn)的理解,就容易多了个唧,因為本質(zhì)上江解,Objective-C的面向?qū)ο螅褪鞘褂眠@些東西構(gòu)建出來的坑鱼。
我們需要了解的是膘流,對于C語言來說絮缅,除了語言本身定義的數(shù)據(jù)類型鲁沥,程序員想要自定義數(shù)據(jù)類型以供編程使用,結(jié)構(gòu)體是必然選擇耕魄,基于這樣的事實画恰,那么理應(yīng)能夠猜到,Objective-C中的一切面向?qū)ο蟾拍钗T如類允扇、對象等,都是基于C語言的結(jié)構(gòu)體之上構(gòu)建的则奥,而如何進(jìn)行對象方法的調(diào)用考润、類方法調(diào)用等等,則通過Objective-C從smalltalk借鑒過來的消息調(diào)用思想而實現(xiàn)的Runtime思想读处,后者是消息調(diào)用思想的鼻祖糊治。
什么是類和對象
C語言是沒有面向?qū)ο蟾拍畹模挥谢緮?shù)據(jù)類型罚舱、指針井辜、結(jié)構(gòu)體等等。那么如何通過這些概念構(gòu)建面向?qū)ο蟮母拍罟苊疲靼走@個的前提是大體總結(jié)一下對象和類有什么特點粥脚。
類
類是描述一個對象規(guī)格的模板,即它說明了一個對象有什么樣的屬性包个,有什么樣的方法刷允。對象的構(gòu)建,通過指定類碧囊,并且初始化恃锉,從而得到類的實例-對象,那么也就是說類是一種描述實例對象的數(shù)據(jù)結(jié)構(gòu)呕臂。
在Objective-C中破托,標(biāo)準(zhǔn)庫為Foundation,事實上幾乎所有的類都繼承與NSObject歧蒋,那么類具體有如下表現(xiàn)
- 類具有方法和類方法的聲明土砂,描述對象實例有什么方法和類有什么方法
- 類具有屬性的聲明州既,描述對象實例有什么樣的屬性
- 類可以被集成或集成其他類,從而給他人提供或從父類獲取對象描述的規(guī)格信息
對象
對象是一個根據(jù)類實例化出來的數(shù)據(jù)結(jié)構(gòu)萝映。具有實例方法吴叶,實例變量,對象沒有繼承概念序臂,只有持有其他對象或被其他對象持有蚌卤,具有以下特點。
- 對象具有實例方法
- 對象具有實例屬性
- 對象可以被其他對象持有或持有其他對象
類和對象的實現(xiàn)
既然類和對象只不過是特點不同的自定義數(shù)據(jù)類型奥秆,那么類和對象必然要使用結(jié)構(gòu)體實現(xiàn)逊彭,Objetcive-C也是這樣設(shè)計的,我們看一下NSObject的定義:
*@interface* NSObject <NSObject> {
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wobjc-interface-ivars"
Class isa OBJC_ISA_AVAILABILITY;
#pragma clang diagnostic pop
}
+ (void)load;
+ (void)initialize;
- (instancetype)init
#if NS_ENFORCE_NSOBJECT_DESIGNATED_INITIALIZER
NS_DESIGNATED_INITIALIZER
#endif
;
+ (instancetype) new OBJC_SWIFT_UNAVAILABLE("use object initializers instead");
+ (instancetype)allocWithZone:(struct _NSZone )zone OBJC_SWIFT_UNAVAILABLE("use object initializers instead");
*@end*
NSObject的定義中构订,有類方法定義侮叮、屬性定義、實例方法定義悼瘾,如何使用C語言的結(jié)構(gòu)體來表達(dá)和存儲這樣的自定義數(shù)據(jù)結(jié)構(gòu)呢囊榜?NSObject是一個Class也就是一個類,在描述中有一個Class isa的變量亥宿,按圖索驥查找到Class的數(shù)據(jù)結(jié)構(gòu):
typedef struct objc_class *Class; //class是一個objc_class結(jié)構(gòu)體的指針
struct objc_class {
Class isa OBJC_ISA_AVAILABILITY;
#if !__OBJC2__
Class super_class OBJC2_UNAVAILABLE;
const char *name OBJC2_UNAVAILABLE;
long version OBJC2_UNAVAILABLE;
long info OBJC2_UNAVAILABLE;
long instance_size OBJC2_UNAVAILABLE;
struct objc_ivar_list *ivars OBJC2_UNAVAILABLE;
struct objc_method_list **methodLists OBJC2_UNAVAILABLE;
struct objc_cache *cache OBJC2_UNAVAILABLE;
struct objc_protocol_list *protocols OBJC2_UNAVAILABLE;
#endif
} OBJC2_UNAVAILABLE; //objc_class是一個結(jié)構(gòu)體卸勺,描述了一個類的信息
從上面定義可以看出來,一個類包含哪些信息烫扼,是通過objc_class 結(jié)構(gòu)體來表示的曙求,NSObject的定義中,有一個Class isa屬性材蛛,而Class是一個指向objc_class結(jié)構(gòu)體的指針圆到,也就是說,NSObject通過isa指針來尋找到其類的信息所在的結(jié)構(gòu)體卑吭。
該結(jié)構(gòu)體中有幾個比較重要的變量:
- Class isa OBJC_ISA_AVAILABILITY; 又是一個指向objc_class結(jié)構(gòu)體的指針芽淡,指向另外一個類信息的結(jié)構(gòu)體,那么一個類指向一個說明其規(guī)格的類結(jié)構(gòu)體豆赏,其意義是來描述類的信息挣菲,一般稱描述類的結(jié)構(gòu)的數(shù)據(jù)類型稱之為元類,即meta-class掷邦,以為著使用元類來描述類的規(guī)格白胀,那么從對象與類的關(guān)系類比中,可以將類看作是元類的實例抚岗,也就說或杠,元類是類對象的類。
- super_class 是該類父類的信息宣蔚,使用super_class指針向抢,找到父類信息的結(jié)構(gòu)體认境。NSObject的實例對象的superclass為null
- long info OBJC2_UNAVAILABLE; 類信息,供運(yùn)行期使用的一些位標(biāo)識
- long instance_size OBJC2_UNAVAILABLE; /該類的實例變量大小
- struct objc_ivar_list *ivars OBJC2_UNAVAILABLE; 類的成員變量鏈表
- struct objc_method_list methodLists OBJC2_UNAVAILABLE; 方法定義的鏈表
- struct objc_cache *cache OBJC2_UNAVAILABLE; 方法緩存挟鸠,對象接到一個消息會根據(jù)isa指針查找消息對象叉信,這時會在methodLists中遍歷,如果cache了艘希,常用的方法調(diào)用時就能夠提高調(diào)用的效率硼身。
- struct objc_protocol_list *protocols OBJC2_UNAVAILABLE; 協(xié)議鏈表
類的實例->對象也是通過一個objc_class結(jié)構(gòu)體描述其結(jié)構(gòu)。如下:
struct objc_object {
Class isa OBJC_ISA_AVAILABILITY;
};
typedef struct objc_object *id;
id 類型覆享,即對象佳遂,其為一個指向objc_object結(jié)構(gòu)體的指針,意味著任意一個Objective-C的對象淹真,其本質(zhì)是一個指向objc_object的結(jié)構(gòu)體指針讶迁,而objc_object結(jié)構(gòu)體中连茧,有一個isa指針核蘸,指向objc_class結(jié)構(gòu)體,來描述其屬于哪個類啸驯,也就是上面的類信息結(jié)構(gòu)體客扎。
當(dāng)定義一個類的時候,如下:
//main.m
@interface ClassA : NSObject
@property(nonatomic,copy)NSString * name;
-(void)sayHello;
+(void)SayHello;
@end
@implementation ClassA
-(void)sayHello{
NSLog(@"object say hello");
}
+(void)SayHello{
NSLog(@"class say hello");
}
@end
int main(int argc, const char * argv[]) {
@autoreleasepool {
NSLog(@"Hello, World!");
NSObject * obj1 = [[NSObject alloc]init];
ClassA * obj2 = [[ClassA alloc]init];
[obj2 sayHello];
[ClassA SayHello];
NSLog(@"%@", NSStringFromClass([obj1 superclass]));
}
return 0;
}
從上面的定義中罚斗,按照之前的說明徙鱼,將該文件轉(zhuǎn)換為C++代碼,將在C++代碼中得到確切的信息针姿。
# 得到main.cpp文件
clang -rewrite-objc main.m
對于NSObject這個類袱吆,可以得到:
#ifndef _REWRITER_typedef_NSObject
#define _REWRITER_typedef_NSObject
typedef struct objc_object NSObject;
typedef struct {} _objc_exc_NSObject;
#endif
NSObject是一個objc_object結(jié)構(gòu)體。
ClassA的結(jié)構(gòu)如下:
typedef struct objc_object ClassA;
ClassA是一個指向objc_object結(jié)構(gòu)體距淫,其相關(guān)的其他部分為:
#ifndef _REWRITER_typedef_ClassA
#define _REWRITER_typedef_ClassA
typedef struct objc_object ClassA;
typedef struct {} _objc_exc_ClassA;
#endif
extern "C" unsigned long OBJC_IVAR_$_ClassA$_name;
struct ClassA_IMPL {
struct NSObject_IMPL NSObject_IVARS;
NSString *_name;
};
// @property(nonatomic,copy)NSString * name;
// -(void)sayHello;
// +(void)SayHello;
/* @end */
// @implementation ClassA
static void _I_ClassA_sayHello(ClassA * self, SEL _cmd) {
NSLog((NSString *)&__NSConstantStringImpl__var_folders_dn_6w6g4h112csgf73k_bz07xpr0000gn_T_main_08dee3_mi_0);
}
static void _C_ClassA_SayHello(Class self, SEL _cmd) {
NSLog((NSString *)&__NSConstantStringImpl__var_folders_dn_6w6g4h112csgf73k_bz07xpr0000gn_T_main_08dee3_mi_1);
}
static NSString * _I_ClassA_name(ClassA * self, SEL _cmd) { return (*(NSString **)((char *)self + OBJC_IVAR_$_ClassA$_name)); }
extern "C" __declspec(dllimport) void objc_setProperty (id, SEL, long, id, bool, bool);
static void _I_ClassA_setName_(ClassA * self, SEL _cmd, NSString *name) { objc_setProperty (self, _cmd, __OFFSETOFIVAR__(struct ClassA, _name), (id)name, 0, 1); }
// @end
這個結(jié)構(gòu)中绞绒,清楚地描述出了ClassA類中的實例變量、類方法榕暇、實例方法的結(jié)構(gòu)和實現(xiàn)蓬衡。
ClassA是一個objc_object結(jié)構(gòu)體,其類方法和靜態(tài)方法在聲明以后彤枢,被使用在如下:
extern "C" unsigned long int OBJC_IVAR_$_ClassA$_name __attribute__ ((used, section ("__DATA,__objc_ivar"))) = __OFFSETOFIVAR__(struct ClassA, _name);
static struct /*_ivar_list_t*/ {
unsigned int entsize; // sizeof(struct _prop_t)
unsigned int count;
struct _ivar_t ivar_list[1];
} _OBJC_$_INSTANCE_VARIABLES_ClassA __attribute__ ((used, section ("__DATA,__objc_const"))) = {
sizeof(_ivar_t),
1,
{{(unsigned long int *)&OBJC_IVAR_$_ClassA$_name, "_name", "@\"NSString\"", 3, 8}}
};
static struct /*_method_list_t*/ {
unsigned int entsize; // sizeof(struct _objc_method)
unsigned int method_count;
struct _objc_method method_list[3];
} _OBJC_$_INSTANCE_METHODS_ClassA __attribute__ ((used, section ("__DATA,__objc_const"))) = {
sizeof(_objc_method),
3,
{{(struct objc_selector *)"sayHello", "v16@0:8", (void *)_I_ClassA_sayHello},
{(struct objc_selector *)"name", "@16@0:8", (void *)_I_ClassA_name},
{(struct objc_selector *)"setName:", "v24@0:8@16", (void *)_I_ClassA_setName_}}
};
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_ClassA __attribute__ ((used, section ("__DATA,__objc_const"))) = {
sizeof(_objc_method),
1,
{{(struct objc_selector *)"SayHello", "v16@0:8", (void *)_C_ClassA_SayHello}}
};
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_ClassA __attribute__ ((used, section ("__DATA,__objc_const"))) = {
sizeof(_prop_t),
1,
{{"name","T@\"NSString\",C,N,V_name"}}
};
OBJC_INSTANCE_METHODS_ClassA ,OBJC_PROP_LIST_ClassA為該類的類方法狰晚、屬性、實例方法等定義的結(jié)構(gòu)體缴啡,這些結(jié)構(gòu)體的被用到在:
static struct _class_ro_t _OBJC_CLASS_RO_$_ClassA __attribute__ ((used, section ("__DATA,__objc_const"))) = {
0, __OFFSETOFIVAR__(struct ClassA, _name), sizeof(struct ClassA_IMPL),
(unsigned int)0,
0,
"ClassA",
(const struct _method_list_t *)&_OBJC_$_INSTANCE_METHODS_ClassA,
0,
(const struct _ivar_list_t *)&_OBJC_$_INSTANCE_VARIABLES_ClassA,
0,
(const struct _prop_list_t *)&_OBJC_$_PROP_LIST_ClassA,
};
OBJC_CLASS_RO$_ClassA 結(jié)構(gòu)體變量將類方法壁晒、屬性等結(jié)構(gòu)體進(jìn)行包裝,其數(shù)據(jù)類型_class_ro_t如下:
struct _class_ro_t {
unsigned int flags;
unsigned int instanceStart;
unsigned int instanceSize;
unsigned int reserved;
const unsigned char *ivarLayout;
const char *name;
const struct _method_list_t *baseMethods;
const struct _objc_protocol_list *baseProtocols;
const struct _ivar_list_t *ivars;
const unsigned char *weakIvarLayout;
const struct _prop_list_t *properties;
};
該結(jié)構(gòu)體其實就是objc_class結(jié)構(gòu)體的變形业栅,代表根類的結(jié)構(gòu)體類型秒咐。 OBJC_CLASS_RO$_ClassA又被另外一個結(jié)構(gòu)體進(jìn)行包裝:
extern "C" __declspec(dllexport) struct _class_t OBJC_CLASS_$_ClassA __attribute__ ((used, section ("__DATA,__objc_data"))) = {
0, // &OBJC_METACLASS_$_ClassA,
0, // &OBJC_CLASS_$_NSObject,
0, // (void *)&_objc_empty_cache,
0, // unused, was (void *)&_objc_empty_vtable,
&_OBJC_CLASS_RO_$_ClassA,
};
OBJC_CLASS_$_ClassA 則就是ClassA這個類的結(jié)構(gòu)體换棚,其結(jié)構(gòu)體是_class_t。
struct _class_t {
struct _class_t *isa;
struct _class_t *superclass;
void *cache;
void *vtable;
struct _class_ro_t *ro;
};
OBJC_CLASS__ClassA兩個結(jié)構(gòu)體被用在:
static void OBJC_CLASS_SETUP_$_ClassA(void ) {
OBJC_METACLASS_$_ClassA.isa = &OBJC_METACLASS_$_NSObject;
OBJC_METACLASS_$_ClassA.superclass = &OBJC_METACLASS_$_NSObject;
OBJC_METACLASS_$_ClassA.cache = &_objc_empty_cache;
OBJC_CLASS_$_ClassA.isa = &OBJC_METACLASS_$_ClassA;
OBJC_CLASS_$_ClassA.superclass = &OBJC_CLASS_$_NSObject;
OBJC_CLASS_$_ClassA.cache = &_objc_empty_cache;
}
這是一個類初始化函數(shù)反镇,從函數(shù)中得到明確的信息是:
- OBJC_METACLASS__NSObject結(jié)構(gòu)體,其類型為_class_ro_t(objc_class)的結(jié)構(gòu)體
- OBJC_METACLASS__NSObject結(jié)構(gòu)體指針
- OBJC_CLASS__ClassA
- OBJC_CLASS__NSObject根類數(shù)據(jù)結(jié)構(gòu)
至此歹茶,可以非常清晰得出以下結(jié)論:
如下圖所示:
- ClassA的實例對象夕玩,是一個objc_object結(jié)構(gòu)體指針,其isa指針指向ClassA類的objc_object結(jié)構(gòu)體
- ClassA惊豺,是一個_class_t(即objc_class)的結(jié)構(gòu)體燎孟,其isa指針指向MetaClassA結(jié)構(gòu)體
- ClassA的父類,是NSObject尸昧,其superclass是一個指向NSObject類對象的isa指針
- ClassA的元類揩页,是MetaClassA,OBJC_METACLASS_元類結(jié)構(gòu)體表明烹俗,其isa指針指向MetaNSObject結(jié)構(gòu)體指針
- 一個類所擁有的方法爆侣、屬性,都會存儲在類的元類中幢妄,當(dāng)調(diào)用對象的方法的時候兔仰,也就是向?qū)ο蟀l(fā)送消息,runtime會在這個對象所屬的類方法列表中查找消息對應(yīng)的方法蕉鸳,但向類發(fā)送消息的時候乎赴,runtime就會在這個類的meta class的方法列表中查找。
更加通用和清晰的關(guān)系圖如下:
即:
- 對象的isa指針指向類對象
- 對象的superclass的指針指向父類類對象
- 類對象的isa指針指向元類
- 類對象的superclass的指針指向父類元類
- 元類的isa指針潮尝,指向根類(NSObject)元類
- 元類的superclass指針指向父類元類榕吼,直接繼承根類的類的元類的superclass指向根類元類(NSObject)
- 根類(NSObject)的isa,指向根元類
- 根類(NSObject)的superclass為nil
- 根元類的superclass指向NSObject類
- 根元類的isa指針勉失,指向自身
類與對象的相關(guān)信息
name
const char * class_getName(Class cls);
super_class和meta-class
//獲取父類
Class class_getSuperclass(Class cls);
//判定類是否為一個meta class
BOOL class_isMetaClass(Class cls);
instance_size
size_t class_gerInstanceSize(Class cls);
objc_ivar_list與objc_method
//objc_ivar_list結(jié)構(gòu)體存儲objc_ivar數(shù)組列表
struct objc_ivar_list {
int ivar_count OBJC2_UNAVAILABLE;
#ifdef __LP64__
int space OBJC2_UNAVAILABLE;
#endif
/* variable length structure */
struct objc_ivar ivar_list[1] OBJC2_UNAVAILABLE;
} OBJC2_UNAVAILABLE;
//objc_method_list結(jié)構(gòu)體存儲著objc_method的數(shù)組列表
struct objc_method_list {
struct objc_method_list *obsolete OBJC2_UNAVAILABLE;
int method_count OBJC2_UNAVAILABLE;
#ifdef __LP64__
int space OBJC2_UNAVAILABLE;
#endif
/* variable length structure */
struct objc_method method_list[1] OBJC2_UNAVAILABLE;
}
objc_ivar_list 為成員變量單向鏈表羹蚣,其結(jié)構(gòu)體最后一個成員變量是一個objc_ivar結(jié)構(gòu)體數(shù)組,該數(shù)組為變長戴质,所以objc_ivar_list可以是一個變長結(jié)構(gòu)體度宦,objc_ivar標(biāo)示一個成員變量:
struct objc_ivar {
char * _Nullable ivar_name OBJC2_UNAVAILABLE;//變量名
char * _Nullable ivar_type OBJC2_UNAVAILABLE;//變量類型
int ivar_offset OBJC2_UNAVAILABLE;
#ifdef __LP64__
int space OBJC2_UNAVAILABLE;
#endif
} OBJC2_UNAVAILABLE;
objc_method_list為方法列表
struct objc_method_list {
struct objc_method_list * _Nullable obsolete OBJC2_UNAVAILABLE;
int method_count OBJC2_UNAVAILABLE;
#ifdef __LP64__
int space OBJC2_UNAVAILABLE;
#endif
/* variable length structure */
struct objc_method method_list[1] OBJC2_UNAVAILABLE;
}
objc_method為方法結(jié)構(gòu)體,如下:
struct objc_method {
SEL _Nonnull method_name OBJC2_UNAVAILABLE;
char * _Nullable method_types OBJC2_UNAVAILABLE;
IMP _Nonnull method_imp OBJC2_UNAVAILABLE;
}
IMP與SEL
typedef struct *SEL;
#if !OBJC_OLD_DISPATCH_PROTOTYPES
typedef void (*IMP)(void /* id, SEL, ... */ );
#else
typedef id _Nullable (*IMP)(id _Nonnull, SEL _Nonnull, ...);
#endif
IMP是一個void * ()的函數(shù)指針告匠,實際上就是方法的實現(xiàn)戈抄,SEL為一個char * 字符串。
每一個objc_class結(jié)構(gòu)體中都有objc_method_list列表后专,而objc_method_list列表中有objc_method結(jié)構(gòu)體划鸽,該結(jié)構(gòu)體為一個SEL對應(yīng)一個IMP實現(xiàn)。
在runtime運(yùn)行的時候,加載的每一個類對應(yīng)有一個virtual table裸诽,用來緩存SEL與IMP的對應(yīng)關(guān)系嫂用,從而能夠通過SEL快速找到其對應(yīng)實現(xiàn)。
成員變量(ivars)及其屬性
//成員變量操作函數(shù)
// 獲取類中指定名稱實例成員變量的信息
Ivar class_getInstanceVariable ( Class cls, const char *name );
// 獲取類成員變量的信息
Ivar class_getClassVariable ( Class cls, const char *name );
// 添加成員變量
BOOL class_addIvar ( Class cls, const char *name, size_t size, uint8_t alignment, const char *types ); //這個只能夠向在runtime時創(chuàng)建的類添加成員變量
// 獲取整個成員變量列表
Ivar * class_copyIvarList ( Class cls, unsigned int *outCount ); //必須使用free()來釋放這個數(shù)組
//屬性操作函數(shù)
// 獲取類中指定名稱實例成員變量的信息
Ivar class_getInstanceVariable ( Class cls, const char *name );
// 獲取類成員變量的信息
Ivar class_getClassVariable ( Class cls, const char *name );
// 添加成員變量
BOOL class_addIvar ( Class cls, const char *name, size_t size, uint8_t alignment, const char *types );
// 獲取整個成員變量列表
Ivar * class_copyIvarList ( Class cls, unsigned int *outCount );
methodLists
// 添加方法
BOOL class_addMethod ( Class cls, SEL name, IMP imp, const char *types ); //和成員變量不同的是可以為類動態(tài)添加方法丈冬。如果有同名會返回NO嘱函,修改的話需要使用method_setImplementation
// 獲取實例方法
Method class_getInstanceMethod ( Class cls, SEL name );
// 獲取類方法
Method class_getClassMethod ( Class cls, SEL name );
// 獲取所有方法的數(shù)組
Method * class_copyMethodList ( Class cls, unsigned int *outCount );
// 替代方法的實現(xiàn)
IMP class_replaceMethod ( Class cls, SEL name, IMP imp, const char *types );
// 返回方法的具體實現(xiàn)
IMP class_getMethodImplementation ( Class cls, SEL name );
IMP class_getMethodImplementation_stret ( Class cls, SEL name );
// 類實例是否響應(yīng)指定的selector
BOOL class_respondsToSelector ( Class cls, SEL sel );
objc_protocol_list與Protocol
objc_protocol_list:
struct objc_protocol_list {
struct objc_protocol_list * _Nullable next;
long count;
__unsafe_unretained Protocol * _Nullable list[1];
};
Protocol的定義如下:
#ifdef __OBJC__
@class Protocol;
#else
typedef struct objc_object Protocol;
#endif
對protocol的操作為:
// 添加協(xié)議
BOOL class_addProtocol ( Class cls, Protocol *protocol );
// 返回類是否實現(xiàn)指定的協(xié)議
BOOL class_conformsToProtocol ( Class cls, Protocol *protocol );
// 返回類實現(xiàn)的協(xié)議列表
Protocol * class_copyProtocolList ( Class cls, unsigned int *outCount );
總結(jié)
Objective-C基于C語言的結(jié)構(gòu)體定義面向?qū)ο蟮拇蟛糠指拍睿媒Y(jié)構(gòu)體指針與函數(shù)指針埂蕊,來實現(xiàn)面向?qū)ο蟮念惗x往弓、類繼承、實例化對象蓄氧、對象成員變量和方法的存儲與定義函似。
由此,Objective-C這本語言是一種在運(yùn)行時發(fā)揮強(qiáng)大能力的語言喉童,而這又歸功于runtime這一消息分發(fā)系統(tǒng)撇寞,在運(yùn)行時能夠?qū)︻愡M(jìn)行掃描、查找堂氯、調(diào)用蔑担、修改等等,這部分知識被稱為rumtime核心技術(shù)祖灰,消息調(diào)用與動態(tài)類型的結(jié)合钟沛,使得Objective-C這門語言能夠給予程序員非常大的自由度去享受編程的樂趣畔规。