動(dòng)態(tài):
主要是將數(shù)據(jù)類型的確定由編譯時(shí),推遲到了運(yùn)行時(shí)。
這個(gè)問題其實(shí)淺涉及到兩個(gè)概念,運(yùn)行時(shí)和多態(tài)。 簡(jiǎn)單來說,運(yùn)行時(shí)機(jī)制使我們直到運(yùn)行時(shí)才去決定一個(gè)對(duì)象的類別,以及調(diào)用該類別對(duì)象指定方法。
現(xiàn)在,讓我來想想OC的動(dòng)態(tài)語(yǔ)言特性。OC的動(dòng)態(tài)特性表現(xiàn)為了三個(gè)方面:動(dòng)態(tài)類型、動(dòng)態(tài)綁定、動(dòng)態(tài)加載。之所以叫做動(dòng)態(tài),是因?yàn)楸仨毜竭\(yùn)行時(shí)(run time)才會(huì)做一些事情。
(1)動(dòng)態(tài)類型
動(dòng)態(tài)類型,說簡(jiǎn)單點(diǎn)就是id類型。動(dòng)態(tài)類型是跟靜態(tài)類型相對(duì)的。像內(nèi)置的明確的基本類型都屬于靜態(tài)類型(int、NSString等)。靜態(tài)類型在 編譯的時(shí)候就能被識(shí)別出來。所以,若程序發(fā)生了類型不對(duì)應(yīng),編譯器就會(huì)發(fā)出警告。而動(dòng)態(tài)類型就編譯器編譯的時(shí)候是不能被識(shí)別的,要等到運(yùn)行時(shí)(run time),即程序運(yùn)行的時(shí)候才會(huì)根據(jù)語(yǔ)境來識(shí)別。所以這里面就有兩個(gè)概念要分清:編譯時(shí)跟運(yùn)行時(shí)。
id obj = someInstance;
if ([obj isKindOfClass:someClass]) {
someClass *classSpecifiedInstance = (someClass *)obj;
}
(2)動(dòng)態(tài)綁定
動(dòng)態(tài)綁定(dynamic binding)貌似比較難記憶,但事實(shí)上很簡(jiǎn)單,只需記住關(guān)鍵詞@selector/SEL即可。先來看看“函數(shù)”,對(duì)于其他一些靜態(tài)語(yǔ)言,比如 c++,一般在編譯的時(shí)候就已經(jīng)將將要調(diào)用的函數(shù)的函數(shù)簽名都告訴編譯器了。靜態(tài)的,不能改變。而在OC中,其實(shí)是沒有函數(shù)的概念的,我們叫“消息機(jī) 制”,所謂的函數(shù)調(diào)用就是給對(duì)象發(fā)送一條消息。這時(shí),動(dòng)態(tài)綁定的特性就來了。OC可以先跳過編譯,到運(yùn)行的時(shí)候才動(dòng)態(tài)地添加函數(shù)調(diào)用,在運(yùn)行時(shí)才決定要調(diào) 用什么方法,需要傳什么參數(shù)進(jìn)去。這就是動(dòng)態(tài)綁定,要實(shí)現(xiàn)他就必須用SEL變量綁定一個(gè)方法。最終形成的這個(gè)SEL變量就代表一個(gè)方法的引用。這里要注意 一點(diǎn):SEL并不是C里面的函數(shù)指針,雖然很像,但真心不是函數(shù)指針。SEL變量只是一個(gè)整數(shù),他是該方法的ID,@selector()就是取類方法的編號(hào)。以前的函數(shù)調(diào)用,是根據(jù)函數(shù)名,也就是 字符串去查找函數(shù)體。但現(xiàn)在,我們是根據(jù)一個(gè)ID整數(shù)來查找方法,整數(shù)的查找字自然要比字符串的查找快得多!所以,動(dòng)態(tài)綁定的特定不僅方便,而且效率更 高。
由于OC的動(dòng)態(tài)特性,在OC中其實(shí)很少提及“函數(shù)”的概念,傳統(tǒng)的函數(shù)一般在編譯時(shí)就已經(jīng)把參數(shù)信息和函數(shù)實(shí)現(xiàn)打包到編譯后的源碼中了,而在OC中最常使 用的是消息機(jī)制。調(diào)用一個(gè)實(shí)例的方法,所做的是向該實(shí)例的指針發(fā)送消息,實(shí)例在收到消息后,從自身的實(shí)現(xiàn)中尋找響應(yīng)這條消息的方法
(3)動(dòng)態(tài)加載
根據(jù)需求加載所需要的資源,這點(diǎn)很容易理解,對(duì)于iOS開發(fā)來說,基本就是根據(jù)不同的機(jī)型做適配。最經(jīng)典的例子就是在Retina設(shè)備上加載@2x的圖片,而在老一些的普通屏設(shè)備上加載原圖。
如有不當(dāng)、錯(cuò)誤之處,歡迎指正!