標籤:style blog color 使用 strong 資料 ar 代碼
ruby具有在運行時執行以字串形式儲存的代碼的功能設施,eval族方法 。包括Kernel#eval,Object#instance_eval,Module#class_eval。
Kernel#eval
它是最直接的方法
如下:
1 p eval("2+2")2 3 eval("def m;p ‘hello world‘;end")4 eval("m")
輸出
4
"hello world"
eval強大而危險,有代碼注入之類的危險,儘管ruby中有一個全域變數$SAFE來控制它,但最好還是不要用它。
Object#instance_eval
該方法將self變為instance_eval調用的接收者,對字串或者代碼塊求值。
如下:
1 p self2 3 a = []4 a.instance_eval {p self}
輸出
main
[]
instance_eval常常用於訪問其他對象的私人資料--特別是執行個體變數
如下:
1 class C2 def initialize3 @x = 14 end5 end6 7 c = C.new8 c.instance_eval {puts @x}
輸出
1
instance_eval也可以接受字串,訪問局部變數。
如下:
1 arr = [‘a‘,‘b‘,‘c‘]2 ch = ‘d‘3 arr.instance_eval "self[1] = ch"4 p arr
輸出
["a", "d", "c"]
instance_eval中定義方法,則會是個單例方法
如下:
1 obj = Object.new2 3 obj.instance_eval do4 def method5 p "hello world"6 end7 end8 p obj.singleton_methods
輸出
[:method]
Module#class_eval
class_eval和module_eval是一樣的。它可以進入類定義體內。
1 C = Class.new2 C.class_eval do3 def method4 p "hello world"5 end6 end7 c = C.new8 c.method
輸出
"hello world"
class_eval可以做一些class關鍵字不能做的事
- 在類定義的上下文中對字串求值
- 為匿名類(但不包含單例類)開啟類定義(也就是說在不知道類的名字的情況就開啟一個類)
- 擷取外圍範圍中變數的訪問權
1 def add_method_to(a_class)2 a_class.class_eval do3 def method ; p "hello world";end4 end5 end6 add_method_to String7 "abc".method
輸出
"hello world"
1 var = "hello world"2 3 class C4 end5 C.instance_eval {puts var}
輸出
"hello world"
總結:instance_eval()方法僅僅會改變self ,而 class_eval()會同時修改self和當前類,通過修改當前類,class_eval()實際上是重新開啟了該類,就像class關鍵字一樣。
Module#class_eval()比class關鍵字更加靈活,class關鍵字只能使用常量,而class_eval()可以對任何代表類的變數使用class_eval()方法。class會開啟一個新的範圍,但是class_eval()其實是扁平化範圍。