日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

详解Objective-C的meta-class

發(fā)布時間:2023/12/9 编程问答 28 豆豆
生活随笔 收集整理的這篇文章主要介紹了 详解Objective-C的meta-class 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

2019獨(dú)角獸企業(yè)重金招聘Python工程師標(biāo)準(zhǔn)>>>

比較簡單的一篇英文,重點(diǎn)是講解meta-class。翻譯下,加深理解。

原文標(biāo)題:What is a meta-class in Objective-C?

原文地址:http://www.cocoawithlove.com/2010/01/what-is-meta-class-in-objective-c.html

?

本篇將會探討一個在Objective-C中相對陌生的概念 -- meta-class。OC中的每一個類都會有一個與之相關(guān)聯(lián)的meta class,但是你卻幾乎永遠(yuǎn)也不會直接使用到,它們始終籠罩著一層神秘的面紗。筆者將以運(yùn)行時動態(tài)創(chuàng)建一個class為引,通過剖析創(chuàng)建的class pair來弄明白到底meta-class是什么以及更深入的了解它對于OC中對象、類的意義。

?

在運(yùn)行時創(chuàng)建類

以下代碼演示運(yùn)行時創(chuàng)建一個NSError的子類,同時添加一個實例方法給它:

Class newClass = objc_allocateClassPair([NSError class], "RuntimeErrorSubclass", 0); class_addMethod(newClass, @selector(report), (IMP)ReportFunction, "v@:"); objc_registerClassPair(newClass);

函數(shù)ReportFunction就是添加的實例方法的具體實現(xiàn),如下:

void?ReportFunction(id?self,?SEL?_cmd)?? {??NSLog(@"This?object?is?%p.",self);??NSLog(@"Class?is?%@,?and?super?is?%@.",[self?class],[self?superclass]);??Class?currentClass?=?[self?class];??for(?int?i?=?1;?i?<?5;?++i?)??{??NSLog(@"Following?the?isa?pointer?%d?times?gives?%p",i,currentClass);??currentClass?=?object_getClass(currentClass);??}??NSLog(@"NSObject's?class?is?%p",?[NSObject?class]);??NSLog(@"NSObject's?meta?class?is?%p",object_getClass([NSObject?class]));?? }??


看起來一切都很簡單,運(yùn)行時創(chuàng)建類只需要三步:
1、為"class pair"分配空間(使用objc_allocateClassPair).
2、為創(chuàng)建的類添加方法和成員(上例使用class_addMethod添加了一個方法)。

3、注冊你創(chuàng)建的這個類,使其可用(使用objc_registerClassPair)。

?

估計讀者馬上就要問:什么是“class pair"? objc_allocateClassPair只返回一個值:Class。那么pair的另一半在哪里呢?

是的,估計你已經(jīng)猜到了這個另一半就是meta-class,也就是這篇短文的標(biāo)題,但是要解釋清楚它是什么,為什么需要它,還需要交代下OC的對象與類的相關(guān)背景。

?

一個數(shù)據(jù)結(jié)構(gòu)何以成為一個對象?

每個對象都會有一個它所屬的類。這是面向?qū)ο蟮幕靖拍?#xff0c;但是在OC中,這對所有數(shù)據(jù)結(jié)構(gòu)有效。任何數(shù)據(jù)結(jié)構(gòu),只要在恰當(dāng)?shù)奈恢镁哂幸粋€指針指向一個class,那么,它都可以被認(rèn)為是一個對象。
在OC中,一個對象所屬于哪個類,是由它的isa指針指向的。這個isa指針指向這個對象所屬的class。

實際上,OC中對象的定義是如下的樣子:

typedef?struct?objc_object?{??Class?isa;?? }*id;?

?

這個定義表明:任何以一個指向Class的指針作為首個成員的數(shù)據(jù)結(jié)構(gòu)都可以被認(rèn)為是一個objc_object.

最重要的特性就是,你可以向OC中的任何對象發(fā)送消息,如下這樣:

【@”stringValue"?writeToFile:@"/file.txt?atomically:YES? encoding:?NSUTF8StringEncoding?error:NULL];??

?

運(yùn)行原理就是,當(dāng)你向一個OC對象發(fā)送消息時(上文的@“stringValue”),運(yùn)行時庫會根據(jù)對象的isa指針找到這個對象所屬的類(上文為例,會找到NSCFString類).這個類會包含一個所有實例方法的列表及一個指向superclass的指針以便可以找到父類的實例方法。運(yùn)行時庫會在類的方法列表以及父類(們)的方法列表中尋找符合這個selector(上文為例,這個selector是"writeToFile:atomically:encoding:error")的方法。找到后即運(yùn)行這個方法。關(guān)鍵點(diǎn)就是類要定義這個你發(fā)送給對象的消息。


什么是meta-class?
至此,你可能已經(jīng)知道,一個OC的類其實也是一個對象,意思就是你可以向一個類發(fā)送消息。

NSStringEncoding defaultStringEncoding = [NSString defaultStringEncoding];


在這個例子中,defaultStringEncoding 被發(fā)送給了NSString類。因為每一個OC的類本身也是一個對象。也就是說Class的數(shù)據(jù)結(jié)構(gòu)必然也是以isa指針開始的在二進(jìn)制級別上與objc_object是完全兼容的。然后一個類結(jié)構(gòu)的下一個字段一定是一個指向super class的指針(或者指向nil,對于基類而言)。
一個類如何定義有很多方法,依賴于你的運(yùn)行時庫版本,但是不管哪種方法,他們都是以一個isa作為第一個字段,接著是superclass字段。

typedef?struct?objc_class?*Class;?? struct?objc_class{??Class?isa;??Class?super_class;??/*followed?by?runtime?specific?details...*/?? };??

?

為了可以調(diào)用類方法,這個類的isa指針必須指向一個包含這些類方法的類結(jié)構(gòu)體。
這樣就引出了meta-class的概念:meta-class是一個類對象的類。
簡單解釋下:
? ? ? ?當(dāng)你向一個對象發(fā)送消息時,runtime會在這個對象所屬的那個類的方法列表中查找。
? ? ? ?當(dāng)你向一個類發(fā)送消息時,runtime會在這個類的meta-class的方法列表中查找。
meta-class之所以重要,是因為它存儲著一個類的所有類方法。每個類都會有一個單獨(dú)的meta-class,因為每個類的類方法基本不可能完全相同。


meta-class的類又是什么呢?


meta-class,就像Class一樣,也是一個對象。你依舊可以向它發(fā)送消息調(diào)用函數(shù),自然的,meta-class也會有一個isa指針指向其所屬類。所有的meta-class使用基類的meta-class作為他們的所屬類。具體而言,任何NSObject繼承體系下的meta-class都使用NSObject的meta-class作為自己所屬的類。
根據(jù)這個規(guī)則,所有的meta-class使用基類的meta-class作為它們的類,而基類的meta-class也是屬于它自己,也就是說基類的meta-class的isa指針指向它自己。(譯:完美的閉環(huán))


類和meta-class的繼承


就像一個類使用super_class指針指向自己的父類一樣,meta-class的super_class會指向類的super_class的meta-class。一直追溯到基類的meta-class,它的super_class會指向基類自身。(譯:萬物歸根)
這樣一來,整個繼承體系中的實例、類和meta-class都派生自繼承體系中的基類。對于NSObject繼承體系來說,NSObject的實例方法對體系中所有的實例、類和meta-class都是有效的;NSObject的類方法對于體系中所有的類和meta-class都是有效的。
用文字描述總會讓人迷糊,Greg Parker給出了一份精彩的圖譜來展示這些關(guān)系:
點(diǎn)擊打開鏈接


實驗證明:


為了證實以上的論述,讓我們查看下開篇代碼中ReportFunction的輸出。這個函數(shù)的目的就是沿著isa指針進(jìn)行打印。
為了運(yùn)行ErportFunction,我們需要創(chuàng)建一個實例,并調(diào)用report方法。

id?instanceOfNewClass?=?[[newClass?alloc]initWithDomain:@"some?Domain"?code:0?userInfo:nil];?? [instanceOfNewClass?performSelector:@"report)];?? [instanceOfNewClass?release];??



因為我們并沒有對report方法進(jìn)行聲明,所以我們使用performSelector進(jìn)行調(diào)用,這樣避免編譯器警告。

然后ReportFunction函數(shù)會沿著isa進(jìn)行檢索,來告訴我們class,meta-class以及meta-class的class是什么樣的情況:

?

【注:ReportFunction使用object_getClass來獲取isa指針指向的類,因為isa指針是一個受保護(hù)成員,你不能直接訪問其他對象的isa指針。ReportFunction沒有使用class方法是因為在一個類對象上調(diào)用這個方法是無法獲得meta-class的,它只是返回這個類而已。(所以[NSString class]只是返回NSString類,而不是NSString的meta-class]
以下是程序的輸出:

This?object?is?0x10010c810.?? Class?is?RuntimeErrorSubclass,?and?super?is?NSError.?? Followingthe?isa?pointer?1times?gives?0x10010c600?? Followingthe?isa?pointer?2times?gives?0x10010c630?? Followingthe?isa?pointer?3times?gives?0x7fff71038480?? Followingthe?isa?pointer?4times?gives?0x7fff71038480?? NSObject's?class?is?0x7fff710384a8?? NSObject's?meta?class?is?0x7fff71038480??

?

觀察通過isa獲得的地址:
對象的地址是 ? ? ?0x10010c810.
類的地址是 ? ? ? ? 0x10010c600.
類的meta-class地址是 ?0x10010c630.
類的meta-class的類地址是 ? ? ? ? ? ? ? ? 0x7fff71038480.(即NSOjbect的meta-class)
NSObject的meta-class的類地址是它自身。
這些地址的值并不重要,重要的是它們說明了文中討論的從類到meta-class到NSObject的meta-class的整個流程。


結(jié)論:


meta-class是類對象的類,每個類都有自己單獨(dú)的meta-class。所有的類對象并不會屬于同一個meta-class。
meta-class要保證類對象具有繼承體系中基類的所有實例和類方法,以及繼承體系中的所有中間類方法。對于所有NSObject繼承體系下的類,NSObject的實例方法和協(xié)議方法對他們和他們meta-class的對象都要有效。
所有的meta-class使用基類的meta-class作為自己的基類,對于頂層基類的meta-class也是一樣,只是它指向自己而已

轉(zhuǎn)載于:https://my.oschina.net/mexiaobai1315/blog/878712

總結(jié)

以上是生活随笔為你收集整理的详解Objective-C的meta-class的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。