動(dòng)態(tài)方法
????????目的:消除重復(fù)的代碼。
①動(dòng)態(tài)調(diào)用方法
? ? ? ? 調(diào)用方法時(shí)草穆,通常使用(·)裆操,也可以使用Object#send方法代替點(diǎn)標(biāo)識(shí)符來調(diào)用MyClass#my_method方法窗宇。
? ? ? ? 使用send方法仍然調(diào)用了my_method方法厌处,但send方法的第一個(gè)參數(shù)是你要發(fā)送給對(duì)象的消息,也就是方法的名字凝危。
? ? ? ? 像這樣波俄,將調(diào)用的方法名作為參數(shù),這樣就可以在代碼運(yùn)行的最后一刻決定調(diào)用哪個(gè)方法蛾默,這個(gè)技巧稱為動(dòng)態(tài)派發(fā)懦铺。
? ? ? ? 問題:send方法可以調(diào)用私有方法,這是破壞封裝的行為支鸡,可以使用public_send方法代替冬念。
②動(dòng)態(tài)定義方法
? ? ? ? 可以使用Module#define_method方法隨時(shí)定義一個(gè)方法。define_method方法在MyClass內(nèi)部執(zhí)行牧挣,這種在運(yùn)行時(shí)定義方法的技術(shù)成為動(dòng)態(tài)方法急前。用Module#define_method方法代替def關(guān)鍵字定義方法的一個(gè)重要原因就是:define_method方法允許在運(yùn)行時(shí)決定方法的名字。
????????define_method方法是類方法,只有類才能調(diào)用,也是私有方法瀑构。它不能有顯式調(diào)用裆针,也就是不能有接受者,不能self.define_method這樣調(diào)用,可以通過send(:define_method)強(qiáng)制調(diào)用据块。
method_missing方法
????????method_missing是BasicObject的一個(gè)實(shí)例方法,而所有的對(duì)象都繼承自BasicObject類, 當(dāng)調(diào)用一個(gè)方法時(shí),若在祖先鏈中未找到該方法,則會(huì)調(diào)用method_missing方法, BasicObject#method_missing()方法會(huì)拋出一個(gè)NoMethodError進(jìn)行響應(yīng)码邻。
????????覆寫method_missing方法可以讓你調(diào)用實(shí)際上并不存在的方法折剃。
幽靈方法
? ? ? ? 如果需要定義很多相似的方法時(shí)另假,可以通過method_missing()方法來方便開發(fā),使用method_missing()方法處理消息怕犁,從調(diào)用者角度看與普通方法并無差別边篮,但實(shí)際上接收者并沒有相應(yīng)的方法,只是統(tǒng)一進(jìn)行了處理奏甫,這被稱為幽靈方法戈轿。
? ? ? ? Hashie庫中有一個(gè)神奇的類Hash::Mash。如果想添加一個(gè)新的屬性阵子,只要給這個(gè)屬性賦值即可思杯。
? ??????Hash::Mash是Hash類的子類,并且它的屬性是幽靈方法挠进,源碼如下:
動(dòng)態(tài)代理
????????一個(gè)捕獲幽靈方法調(diào)用并把它們轉(zhuǎn)發(fā)給另一個(gè)對(duì)象的對(duì)象,稱為動(dòng)態(tài)代理色乾。
????????注意:使用method_missing技術(shù)后,所有不存在方法的調(diào)用都會(huì)調(diào)用你覆蓋的方法领突,這樣會(huì)導(dǎo)致一些錯(cuò)誤信息(你看不到NoSuchMethod這樣的提示了)暖璧,因此, 在使用method_missing方法的時(shí)候君旦,一定要限定其使用范圍澎办,并且調(diào)用父類的super.method_missing方法,還原錯(cuò)誤處理.
白板類
????????當(dāng)一個(gè)幽靈方法和真實(shí)方法發(fā)生沖突時(shí), 而會(huì)執(zhí)行真實(shí)的方法, 這個(gè)問題就是動(dòng)態(tài)代理的通病, 為了安全起見, 應(yīng)該在代理類中刪除絕大多數(shù)繼承來的方法, 這就是所謂的白板類.?
????????- Module#undef_method()方法會(huì)刪除所有的(包括繼承的)方法?
????????- Module#remove_method()方法只會(huì)刪除接收者自己的(保留繼承的)方法