深入理解alias, alias_method和alias_method_chain
生活随笔
收集整理的這篇文章主要介紹了
深入理解alias, alias_method和alias_method_chain
小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
對(duì)于alias, alias_method, alias_method_chain的深入理解是有益的,因?yàn)閞ails3的源碼里很多地方使用了alias_method_chain的魔法。 有人評(píng)論說(shuō)alias_method_chain使用的過(guò)多不好,具體怎么不好,是后話了,這篇文章集中在理解這3個(gè)方法上面。
如果想轉(zhuǎn)載本文,請(qǐng)注明出處,謝謝!請(qǐng)尊重別人的勞動(dòng)成果,為構(gòu)建豐富web原創(chuàng)內(nèi)容做貢獻(xiàn)!
1. alias
?? Ruby里的關(guān)鍵字,用于定義方法或者全局變量的別名。 例子:
?? class A
???? def m1
?????? puts "m1"
???? end
???? alias m2 m1
??? end
=> nil
a = A.new
=> #<A:0xb7ef5234>
?a.m1
m1
=> nil
a.m2
m1
=> nil
在使用的時(shí)候,注意原有的方法名在最后位置,用空格分開(kāi)。
2. alias_method
作用和alias差不多,是Module的一個(gè)私有實(shí)例方法,只能用于給方法起別名,并且參數(shù)只能是字符串或者符號(hào)(alias后面跟的直接是方法名,不是字符串也不是符號(hào))。例子:
class B
? def b
??? p "b"
? end
? alias_method :c, :b
end
=> B
b = B.new
=> #<B:0xb7ee75bc>
b.c
"b"
=> nil
b.b
"b"
=> nil
注意,alias_method的參數(shù)必須是字符串或者是符號(hào),并且用逗號(hào)分隔。
3. alias_method_chain
是ActiveSupport的一個(gè)公有實(shí)例方法。同樣接受兩個(gè)參數(shù),可以是符號(hào),也可以是字符串,但要注意一下第1個(gè)參數(shù)才是原始方法(alias_method的第2個(gè)參數(shù)是原始方法)。例子:
class A
? def m1
??? puts 'm1'
? end
? def m1_with_m2
??? puts "do something befor m1"
??? m1_without_m2
??? puts "do something after m2"
? end
? alias_method_chain :m1, :m2
end
=> A
a = A.new
=> #<A:0xb7bd9820>
a.m1
do something befor m1
m1
do something after m2
=> nil
上面的代碼用alias或者alias_method也能完成:
class A ?
? def m1 ?
??? puts 'm1' ?
? end
? alias m1_without_m2 m1 ?
? def m1_with_m2 ?
??? puts 'do something else' ?
??? m1_without_m2 ?
? end ?
? alias m1 m1_with_m2 ?
end
那么其原理也一目了然了:
a = A.new
a.m1
當(dāng)調(diào)用m1的時(shí)候, m1_with_m2會(huì)執(zhí)行,? 在puts "do something befor m1"之后,執(zhí)行m1_without_m2,這個(gè)時(shí)候是執(zhí)行了真正的m1方法。 這樣就形成了一個(gè)類似于AOP的行為。
也可以說(shuō),對(duì)外把m1方法隱藏起來(lái)了,對(duì)類外部,實(shí)際上把m1_with_m2改頭換面已經(jīng)成為了另一個(gè)方法,只是我們不知道而已,因?yàn)樗€叫m1.
再來(lái)看看alias_method_chain的源碼:
def alias_method_chain(target, feature)?
? # Strip out punctuation on predicates or bang methods since?
? # e.g. target?_without_feature is not a valid method name.?
? aliased_target, punctuation = target.to_s.sub(/([?!=])$/, ''), $1?
? yield(aliased_target, punctuation) if block_given???????
? with_method, without_method = "#{aliased_target}_with_#{feature}#{punctuation}", "#{aliased_target}_without_#{feature}#{punctuation}"?
? alias_method without_method, target?
? alias_method target, with_method???????
? case?
??? when public_method_defined?(without_method)?
????? public target?
??? when protected_method_defined?(without_method)?
????? protected target?
??? when private_method_defined?(without_method)?
????? private target?
? end?
end
一個(gè)道理。
更實(shí)際的例子:
在一些rails比較老的系統(tǒng)里,搜索功能的日期選擇可能會(huì)用到date_select,這個(gè)方法會(huì)生成類似于這樣的頁(yè)面元素:
search_form[start_from(1i)]年
search_form[start_from(2i)]月
search_form[start_from(3i)]日
把這樣的參數(shù)傳回去,就無(wú)法查詢到對(duì)應(yīng)的日期。這個(gè)時(shí)候我們需要在后臺(tái)得到查詢條件之后來(lái)處理日期,比如:
get_conditions 這個(gè)方法假如是得到頁(yè)面查詢條件的,它返回一個(gè)數(shù)組,這個(gè)時(shí)候我們可以定義:
def get_conditions_with_handle_date
? puts "你可以在get_conditions方法執(zhí)行前干點(diǎn)別的,如果你愿意"
? get_conditions_without_handle_date
? puts "get_conditions執(zhí)行完了,我們可以在其后干點(diǎn)別的,比如說(shuō)處理日期"
? conditions.reject!{|condition|condition[0] =~ /\([1-3]i\)/}?? # 把條件數(shù)組里的1i,2i,3i之類的去掉。
? conditions << ["? <= #{@model.table_name}.created_at", @search.start_from] if @search.start_from? #給搜索對(duì)象里添加正確的查詢?nèi)掌跅l件
? conditions << ["#{@model.table_name}.created_at < ?", @search.end_to + 1.day] if @search.end_to?? #給搜索對(duì)象里添加正確的查詢?nèi)掌跅l件
end
? #然后實(shí)施魔法
? alias_method_chain :get_conditions, :handle_date
這樣我們就搞定了。 創(chuàng)作挑戰(zhàn)賽新人創(chuàng)作獎(jiǎng)勵(lì)來(lái)咯,堅(jiān)持創(chuàng)作打卡瓜分現(xiàn)金大獎(jiǎng)
如果想轉(zhuǎn)載本文,請(qǐng)注明出處,謝謝!請(qǐng)尊重別人的勞動(dòng)成果,為構(gòu)建豐富web原創(chuàng)內(nèi)容做貢獻(xiàn)!
1. alias
?? Ruby里的關(guān)鍵字,用于定義方法或者全局變量的別名。 例子:
?? class A
???? def m1
?????? puts "m1"
???? end
???? alias m2 m1
??? end
=> nil
a = A.new
=> #<A:0xb7ef5234>
?a.m1
m1
=> nil
a.m2
m1
=> nil
在使用的時(shí)候,注意原有的方法名在最后位置,用空格分開(kāi)。
2. alias_method
作用和alias差不多,是Module的一個(gè)私有實(shí)例方法,只能用于給方法起別名,并且參數(shù)只能是字符串或者符號(hào)(alias后面跟的直接是方法名,不是字符串也不是符號(hào))。例子:
class B
? def b
??? p "b"
? end
? alias_method :c, :b
end
=> B
b = B.new
=> #<B:0xb7ee75bc>
b.c
"b"
=> nil
b.b
"b"
=> nil
注意,alias_method的參數(shù)必須是字符串或者是符號(hào),并且用逗號(hào)分隔。
3. alias_method_chain
是ActiveSupport的一個(gè)公有實(shí)例方法。同樣接受兩個(gè)參數(shù),可以是符號(hào),也可以是字符串,但要注意一下第1個(gè)參數(shù)才是原始方法(alias_method的第2個(gè)參數(shù)是原始方法)。例子:
class A
? def m1
??? puts 'm1'
? end
? def m1_with_m2
??? puts "do something befor m1"
??? m1_without_m2
??? puts "do something after m2"
? end
? alias_method_chain :m1, :m2
end
=> A
a = A.new
=> #<A:0xb7bd9820>
a.m1
do something befor m1
m1
do something after m2
=> nil
上面的代碼用alias或者alias_method也能完成:
class A ?
? def m1 ?
??? puts 'm1' ?
? end
? alias m1_without_m2 m1 ?
? def m1_with_m2 ?
??? puts 'do something else' ?
??? m1_without_m2 ?
? end ?
? alias m1 m1_with_m2 ?
end
那么其原理也一目了然了:
a = A.new
a.m1
當(dāng)調(diào)用m1的時(shí)候, m1_with_m2會(huì)執(zhí)行,? 在puts "do something befor m1"之后,執(zhí)行m1_without_m2,這個(gè)時(shí)候是執(zhí)行了真正的m1方法。 這樣就形成了一個(gè)類似于AOP的行為。
也可以說(shuō),對(duì)外把m1方法隱藏起來(lái)了,對(duì)類外部,實(shí)際上把m1_with_m2改頭換面已經(jīng)成為了另一個(gè)方法,只是我們不知道而已,因?yàn)樗€叫m1.
再來(lái)看看alias_method_chain的源碼:
def alias_method_chain(target, feature)?
? # Strip out punctuation on predicates or bang methods since?
? # e.g. target?_without_feature is not a valid method name.?
? aliased_target, punctuation = target.to_s.sub(/([?!=])$/, ''), $1?
? yield(aliased_target, punctuation) if block_given???????
? with_method, without_method = "#{aliased_target}_with_#{feature}#{punctuation}", "#{aliased_target}_without_#{feature}#{punctuation}"?
? alias_method without_method, target?
? alias_method target, with_method???????
? case?
??? when public_method_defined?(without_method)?
????? public target?
??? when protected_method_defined?(without_method)?
????? protected target?
??? when private_method_defined?(without_method)?
????? private target?
? end?
end
一個(gè)道理。
更實(shí)際的例子:
在一些rails比較老的系統(tǒng)里,搜索功能的日期選擇可能會(huì)用到date_select,這個(gè)方法會(huì)生成類似于這樣的頁(yè)面元素:
search_form[start_from(1i)]年
search_form[start_from(2i)]月
search_form[start_from(3i)]日
把這樣的參數(shù)傳回去,就無(wú)法查詢到對(duì)應(yīng)的日期。這個(gè)時(shí)候我們需要在后臺(tái)得到查詢條件之后來(lái)處理日期,比如:
get_conditions 這個(gè)方法假如是得到頁(yè)面查詢條件的,它返回一個(gè)數(shù)組,這個(gè)時(shí)候我們可以定義:
def get_conditions_with_handle_date
? puts "你可以在get_conditions方法執(zhí)行前干點(diǎn)別的,如果你愿意"
? get_conditions_without_handle_date
? puts "get_conditions執(zhí)行完了,我們可以在其后干點(diǎn)別的,比如說(shuō)處理日期"
? conditions.reject!{|condition|condition[0] =~ /\([1-3]i\)/}?? # 把條件數(shù)組里的1i,2i,3i之類的去掉。
? conditions << ["? <= #{@model.table_name}.created_at", @search.start_from] if @search.start_from? #給搜索對(duì)象里添加正確的查詢?nèi)掌跅l件
? conditions << ["#{@model.table_name}.created_at < ?", @search.end_to + 1.day] if @search.end_to?? #給搜索對(duì)象里添加正確的查詢?nèi)掌跅l件
end
? #然后實(shí)施魔法
? alias_method_chain :get_conditions, :handle_date
這樣我們就搞定了。 創(chuàng)作挑戰(zhàn)賽新人創(chuàng)作獎(jiǎng)勵(lì)來(lái)咯,堅(jiān)持創(chuàng)作打卡瓜分現(xiàn)金大獎(jiǎng)
總結(jié)
以上是生活随笔為你收集整理的深入理解alias, alias_method和alias_method_chain的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: SSH远程终端连接数问题
- 下一篇: 2010.7.27 OnDraw与On