Objective-C 面向?qū)ο?一)——對象的本質(zhì)

對于一門編程語言而言,當(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)

  1. 類具有方法和類方法的聲明土砂,描述對象實例有什么方法和類有什么方法
  2. 類具有屬性的聲明州既,描述對象實例有什么樣的屬性
  3. 類可以被集成或集成其他類,從而給他人提供或從父類獲取對象描述的規(guī)格信息

對象

對象是一個根據(jù)類實例化出來的數(shù)據(jù)結(jié)構(gòu)萝映。具有實例方法吴叶,實例變量,對象沒有繼承概念序臂,只有持有其他對象或被其他對象持有蚌卤,具有以下特點。

  1. 對象具有實例方法
  2. 對象具有實例屬性
  3. 對象可以被其他對象持有或持有其他對象

類和對象的實現(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_VARIABLES_ClassA,_OBJC__INSTANCE_METHODS_ClassA ,OBJC_CLASS_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與_OBJC_CLASS_RO__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ù)中得到明確的信息是:

  1. OBJC_METACLASS__ClassA是一個_class_t(即objc_class)結(jié)構(gòu)體固蚤,其isa指針指向OBJC_METACLASS__NSObject結(jié)構(gòu)體,其類型為_class_ro_t(objc_class)的結(jié)構(gòu)體
  2. OBJC_METACLASS__ClassA.superclass指明其父類是OBJC_METACLASS__NSObject結(jié)構(gòu)體指針
  3. OBJC_CLASS__ClassA的isa指針指向ClassA元類結(jié)構(gòu)OBJC_METACLASS__ClassA
  4. OBJC_CLASS__ClassA.superclass指明其父類是OBJC_CLASS__NSObject根類數(shù)據(jù)結(jié)構(gòu)
    至此歹茶,可以非常清晰得出以下結(jié)論:
    如下圖所示:
關(guān)系圖
  1. ClassA的實例對象夕玩,是一個objc_object結(jié)構(gòu)體指針,其isa指針指向ClassA類的objc_object結(jié)構(gòu)體
  2. ClassA惊豺,是一個_class_t(即objc_class)的結(jié)構(gòu)體燎孟,其isa指針指向MetaClassA結(jié)構(gòu)體
  3. ClassA的父類,是NSObject尸昧,其superclass是一個指向NSObject類對象的isa指針
  4. ClassA的元類揩页,是MetaClassA,OBJC_METACLASS_元類結(jié)構(gòu)體表明烹俗,其isa指針指向MetaNSObject結(jié)構(gòu)體指針
  5. 一個類所擁有的方法爆侣、屬性,都會存儲在類的元類中幢妄,當(dāng)調(diào)用對象的方法的時候兔仰,也就是向?qū)ο蟀l(fā)送消息,runtime會在這個對象所屬的類方法列表中查找消息對應(yīng)的方法蕉鸳,但向類發(fā)送消息的時候乎赴,runtime就會在這個類的meta class的方法列表中查找。
    更加通用和清晰的關(guān)系圖如下:
關(guān)系圖

即:

  1. 對象的isa指針指向類對象
  2. 對象的superclass的指針指向父類類對象
  3. 類對象的isa指針指向元類
  4. 類對象的superclass的指針指向父類元類
  5. 元類的isa指針潮尝,指向根類(NSObject)元類
  6. 元類的superclass指針指向父類元類榕吼,直接繼承根類的類的元類的superclass指向根類元類(NSObject)
  7. 根類(NSObject)的isa,指向根元類
  8. 根類(NSObject)的superclass為nil
  9. 根元類的superclass指向NSObject類
  10. 根元類的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這門語言能夠給予程序員非常大的自由度去享受編程的樂趣畔规。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末局扶,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子叁扫,更是在濱河造成了極大的恐慌三妈,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,839評論 6 482
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件莫绣,死亡現(xiàn)場離奇詭異畴蒲,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)对室,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,543評論 2 382
  • 文/潘曉璐 我一進(jìn)店門模燥,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人掩宜,你說我怎么就攤上這事蔫骂。” “怎么了牺汤?”我有些...
    開封第一講書人閱讀 153,116評論 0 344
  • 文/不壞的土叔 我叫張陵辽旋,是天一觀的道長。 經(jīng)常有香客問我,道長补胚,這世上最難降的妖魔是什么码耐? 我笑而不...
    開封第一講書人閱讀 55,371評論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮溶其,結(jié)果婚禮上骚腥,老公的妹妹穿的比我還像新娘。我一直安慰自己瓶逃,他們只是感情好桦沉,可當(dāng)我...
    茶點故事閱讀 64,384評論 5 374
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著金闽,像睡著了一般纯露。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上代芜,一...
    開封第一講書人閱讀 49,111評論 1 285
  • 那天埠褪,我揣著相機(jī)與錄音,去河邊找鬼挤庇。 笑死钞速,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的嫡秕。 我是一名探鬼主播渴语,決...
    沈念sama閱讀 38,416評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼昆咽!你這毒婦竟也來了驾凶?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,053評論 0 259
  • 序言:老撾萬榮一對情侶失蹤掷酗,失蹤者是張志新(化名)和其女友劉穎调违,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體泻轰,經(jīng)...
    沈念sama閱讀 43,558評論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡技肩,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,007評論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了浮声。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片虚婿。...
    茶點故事閱讀 38,117評論 1 334
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖泳挥,靈堂內(nèi)的尸體忽然破棺而出然痊,到底是詐尸還是另有隱情,我是刑警寧澤羡洁,帶...
    沈念sama閱讀 33,756評論 4 324
  • 正文 年R本政府宣布玷过,位于F島的核電站,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏辛蚊。R本人自食惡果不足惜粤蝎,卻給世界環(huán)境...
    茶點故事閱讀 39,324評論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望袋马。 院中可真熱鬧初澎,春花似錦、人聲如沸虑凛。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,315評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽桑谍。三九已至延柠,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間锣披,已是汗流浹背贞间。 一陣腳步聲響...
    開封第一講書人閱讀 31,539評論 1 262
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留雹仿,地道東北人增热。 一個月前我還...
    沈念sama閱讀 45,578評論 2 355
  • 正文 我出身青樓,卻偏偏與公主長得像胧辽,于是被迫代替她去往敵國和親峻仇。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 42,877評論 2 345

推薦閱讀更多精彩內(nèi)容