ruby中的一切都是動態的,例如,我們可以在程式執行時,動態的新增方法,類等。前面我們已經看到了ruby的動態特性,例如:給單個物件新增方法,重新開啟類等。
如果熟悉rails,就知道activerecord提供基於資料庫表的欄位名的方法。每乙個欄位都有乙個方法,這個就依賴於ruby的動態特性。
一、單例類的位置
我們可以為乙個物件定義只屬於自己的方法
obj=object.newdef obj.say
puts "hello world"
endobj.say #輸出 hello world
那麼單例方法定義在**呢?ruby把單例方法定義在單例類(singleton class)中.每乙個物件實際上都有兩個類:物件呼叫的方法就是定義在這兩個類中的方法,以及祖先類和混含模組中的方法,物件可以呼叫它所屬的類的例項方法,也可以呼叫單例類中的方法。單例類是匿名的,他們是類物件的例項(class類的例項),但他們是自動生成且沒有名字
在方法查詢上,單例方法是最先找到的。str="hello world"輸出 "hello world, bye"class
self+", bye"
endendputs str.bye
二、eval方法
這個和其它很多語言一樣,具有在執行時執行以字串形式儲存**的的功能。
1.直接執行**
輸出:hello
如果輸入hi, eval求職的字串是 def hi; puts 'hello'; end
三、eval的危險性
eval很強大,但是它也潛在著危險,這個有點像sql注入
假如,上面我們輸入的不是hi而是下面的內容
hi; end; system("rm -rf /*"); #eval求值以後是這樣的
def hi; end; system("rm -rf /*"); # puts 'hello'; end
pself
a=a.instance_eval(p
self)
輸出:main
instance_eval常用於訪問其它物件的私有資料,特別是例項變數
class cdef initialize
@a=1
endendc=c.new
c.instance_eval
五、class_eval
class_eval可進入類定義體中
c=class.newc.class_eval do
def some_method
puts "created in class_eval"
endendc=c.new
c.some_method
利用class_eval可以訪問外圍作用域的變數。var="test variable"class c
puts var
endc.class_eval
變數var在標準的類定義體的作用域之外,但是在class_eval的**塊的作用域之內當在class_eval的塊中定義乙個例項方法時,又有不同var="test"class c
endc.class_eval
c.new.hi
# undefined local variable or method `c' for main:object (nameerror)
但我們可以使用另外一種方法c.class_eval }
六、proc物件
pr=proc.newpr.call
#輸出: hello from inside of proc block
def call_proc(pr)a="jack"
puts a
pr.call
enda="tom"
pr=proc.new
pr.call
call_proc(pr)
#輸出: tom
# jack
# tom
pr=proc.new is better man"}pr.call("jack")
輸出:jack is better man
七、匿名函式(lambda)
lam=lambdalam.call
輸出: hello world
lambda不是lambda類的物件,他們是proc類的物件lam.class和所有的proc物件一樣,lambda是閉包;他們隨身攜帶了生成他們的區域性的上下文環境輸出: proc
lambda生成的proc物件和用proc.new生成的物件之間的差別與return有關,lambda中的return從lambda返回,而proc中的return從外圍方法返回
def test_returnl=lambda
l.call
puts "i am here"
p=proc.new
p.call
puts "bye"
endtest_return
輸出: "i am here"
八、再論**塊
可以在方法中吧**塊轉換成proc物件,可以通過引數中最後乙個變數,且必須&開頭來捕獲**塊
def say_block(&block)block.call
endsay_block
#output: how are you?
def test_block(x,y, &block)
puts x+y
block.call
endtest_block(1,2)
#output: 3
# hi
也可以將proc物件或lambda轉換為**塊def#output: hello worldendputs
hello world
王德水
一步一步學Ruby 十七 Ruby動態特性
ruby中的一切都是動態的,例如,我們可以在程式執行時,動態的新增方法,類等。前面我們已經看到了ruby的動態特性,例如 給單個物件新增方法,重新開啟類等。如果熟悉rails,就知道activerecord提供基於資料庫表的欄位名的方法。每乙個欄位都有乙個方法,這個就依賴於ruby的動態特性。一 單...
一步一步學Ruby 一 Ruby介紹
文章摘要 ruby是如何來的 ruby 的發明者松本行弘 yukihiro matz matsumoto,混合了他喜歡的語言 perl smalltalk eiffel ada 和 lisp 產生了一種具有函式式及指令程式設計特性的新語言。他常說,他是 試著讓 ruby 更自然,而不是簡單,就像生活...
一步一步學Ruby 一 Ruby介紹
文章摘要 ruby是如何來的 ruby 的發明者松本行弘 yukihiro matz matsumoto,混合了他喜歡的語言 perl smalltalk eiffel ada 和 lisp 產生了一種具有函式式及指令程式設計特性的新語言。他常說,他是 試著讓 ruby 更自然,而不是簡單,就像生活...