eval
將字串作為**來求值,最直接,也是最危險的方法。
編寫乙個讓別人在執行時鍵入方法名的方法:
print "method name:"
m = gets.chomp
eval("def #; puts 'hi!'; end")
eval(m)
如果在執行時,輸入abc,那麼eval求值的字串是:
def abc
puts 'hi!'
endeval的危險性
eval很強大,但是它也潛在著危險,這個有點像sql注入
假如,上面我們輸入的不是hi而是下面的內容
hi; end; system("rm -rf /*"); #
eval求值以後是這樣的
def hi; end; system("rm -rf /*"); # puts 'hello'; end
求值的結果是:#後面的所有內容會被作為注釋忽略掉。使用system命令試圖刪除系統所有檔案
ruby有乙個全域性變數$safe(取值範圍是0到4)、以獲取對如非法寫檔案這一類危險的防護。
instance_eval
該方法是將self變為instance_eval呼叫的接收者,對字串或**塊進行求值。
p self
a =
a.instance_eval
輸出結果:
main
instance_eval常常於用訪問物件的私有資料(特別是例項變數)。
class c
def initialize
@x = 1
endend
c = c.new
c.instance_eval
class_eval
從本質上f講,class_eval(即model_eval)可進入類定義體中:
c = class.new
c.class_eval do
def some_method
puts "created in class_eval"
endend
c = c.new
c.some_method
class_eval還可以做一些class關鍵字不能做的事:
*在類定義的上下文中對字串求值
*為匿名類(不包單例類)開啟類定義
*獲取外圍作用域中變數的訪問權
用class關鍵字開啟乙個類時,就開啟了乙個新的區域性變數作用域。但是,使用class_eval的**塊,可以看到外圍使用域中的變數。
>> var = "initialize variable"
=> "initialized variable"
>> class c
>> puts var
>> end
nameerror: undefined local variable or method 'var' for c:class
from (irb):3
>>c.class_eval
initialized variable
var在標準的類定義體的作用域之外,但是在傳遞給class_eval的**塊的作用域之內。
當在class_eval的塊中定義乙個例項方法時,又有所不同:
>> c.class_eval
=> nil
>>c.new.talk
nameerror: undefined local variable or method 'var' for #
和任何def一樣,在**塊中的def開啟了乙個新的作用域,所以變數var不能訪問了。
如果想要把外部作用域的變數硬塞到例項方法中,可以使用define_method方法。
>>c.class_eval }
>>c.new.talk
initialized variable
define_method是module類的例項方法,所以module或class的任意例項都可以呼叫該方法。
ruby的動態性
記住 ruby的動態特性是以self身份的轉換為基礎的。單例類先來看看什麼是單例類。大多數ruby程式中發生的都涉及包含例項方法定義的類和模組 class c def talk puts hi endend 使用下面的方法例項化和例項方法呼叫 c c.new c.talk 還可以直接給單個物件新增方...
Ruby中的繫結和eval
ruby是一種指令碼語言,他的每一步執行都需要乙個上下文環境,我們知道ruby的頂層環境就是main作為self,ruby的eval可以把傳入的字串當作指令碼 來解釋執行,這裡同樣需要乙個作用域。我們來看乙個實驗 irbname tony eval p name tony def test name...
奇異的家族 動態規劃
有一種奇怪的大家族,這種家族裡的人要麼沒有孩子,要麼就有兩個孩子。已知某個這種家族共有n個人,家族中共有k代人。你能告訴我這樣的乙個家族可能的家譜結構的種數除以9901的餘數是多少嗎?輸入包括一行,包括兩個被空格分開的整數,第乙個為家族中的人數n 3 n 200 第二個為家族中的代數k 1 k 10...