3-15 《元编程》第6章 3-16 hook method
Code That Writes Code?
6.1 Coding your way to the weekend
?
6.2 Kernel#eval, Binding#eval?
Binding:
Objects of class?Binding(類Binding的對象)?encapsulate (密封)the execution context at some particular place in the code and retain this context for future use.
?
如果你想要一段已經執行的代碼在今后反復使用,可以用Binding對象封裝它。
The variables, methods, value of?self, and possibly an iterator block(迭代塊) that can be accessed in this context are all retained.?
變量,方法,自身的value,甚至迭代塊都可以用Binding對象封裝儲存。
Binding objects can be created using?Kernel#binding
?
eval(string [, filename [,lineno]]) → obj
Evaluates the Ruby expression(s) in?string, in the?binding's context.
Binding對象的eval方法,可以評估字符串內的Ruby表達式,并返回表達式的值。
If the optional?filename?and?lineno?parameters are present, they will be used when reporting syntax errors.
?
class Myclass ? def my_method ? ? @x = 1 ? binding ? end end p b = Myclass.new.my_method p b.eval("@x") p eval("@x", b)#結果一樣 1
?
class Anotherclass ? def my_method ? ? # eval "self", TOPLEVEL_BINDING? ?#=> main ? ? eval("xx + yy", TOPLEVEL_BINDING) ? end end xx = 123 yy = 321 obj = Anotherclass.new p obj.my_method #=> 444TOPLEVEL_BINDING: 是預定義常量,表示頂層作用域的Binding對象。
?
6.24 Strings of Code Vs Blocks?
?eval只能執行代碼字符串,instance_eval和class_eval可以執行代碼字符串和block
array = [1,2,3] x = 'd' array.instance_eval("self[1] = x") p array #=> [1, "d", 3] 盡量用block,代碼字符串安全性低容易被攻擊。同時也難以閱讀和修改。?
流行的做法是禁止使用eval方法,同時用Dynamic methods和Dynamic Dispatch替代
?
污染對象?
Ruby把外部傳入的對象標記為污染對象。Object#taint -> obj.
判斷: #tainted? ->true/false
去掉污染 #untaint?
?
謹慎使用安全級別p148頁
可以使用proc {}.call 作為潔凈室
?
?
6.3Hook Method:?
Class#inherited是一個實例方法,當一個類被繼承時,Ruby會調用這個方法,Class#inherited方法什么也不做,但程序員可以覆寫它的行為,像這樣的方法稱為鉤子方法。
inherited(subclass):Callback invoked whenever a subclass of the current class is created.
更多的鉤子方法:
Module#included,#prepended,#method_added, #method_removed, #method_undefined (只對實例方法有用),#singleton_method_added...
?
這種鉤子方法寫在模塊里,用類方法的方式定義:
module M1 ? def self.included(othermod) ? ? puts "m1 was included into #{othermod}" ? end end class C ? include M1 end #=>m1 was included into C另外一種方式鉤住同一個事件,:#include方法可以覆寫 ,但注意寫在類C中。
我的理解類C.調用include方法,就是self.include。先是在自身調用覆寫的include方法,然后用super關鍵字調用原始方法。
?? 類方法是不能被繼承的只能自己用。
?? 類包含模塊后默認是獲得實例方法。除非用#extend
module M ? def hello ? ? puts "world" ? end end class C ? def self.include(mod) ? ? puts "Called: C.include(#{mod})" ? ? super? #因為覆寫了include,所以需要用super調用原始的include功能,否則M不會被C包含 ? end? ? include(M) end C.new.hello??類方法和鉤子方法結合的技巧:P160頁。?
轉載于:https://www.cnblogs.com/chentianwei/p/8574545.html
總結
以上是生活随笔為你收集整理的3-15 《元编程》第6章 3-16 hook method的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 工银微信信用卡怎么申请?申请方式有这些
- 下一篇: NOIP2005普及组第3题 采药 (背