一步一步學Ruby 十七 Ruby動態特性

2021-09-22 09:50:51 字數 4040 閱讀 9979

ruby中的一切都是動態的,例如,我們可以在程式執行時,動態的新增方法,類等。前面我們已經看到了ruby的動態特性,例如:給單個物件新增方法,重新開啟類等。

如果熟悉rails,就知道activerecord提供基於資料庫表的欄位名的方法。每乙個欄位都有乙個方法,這個就依賴於ruby的動態特性。

一、單例類的位置

我們可以為乙個物件定義只屬於自己的方法
obj=object.new

def obj.say

puts "hello world"

endobj.say #輸出 hello world

那麼單例方法定義在**呢?ruby把單例方法定義在單例類(singleton class)中.每乙個物件實際上都有兩個類:
物件呼叫的方法就是定義在這兩個類中的方法,以及祖先類和混含模組中的方法,物件可以呼叫它所屬的類的例項方法,也可以呼叫單例類中的方法。單例類是匿名的,他們是類物件的例項(class類的例項),但他們是自動生成且沒有名字

str="hello world"

class

self+", bye"

endendputs str.bye

輸出 "hello world, 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
p

self

a=a.instance_eval(p

self)

輸出:main

instance_eval常用於訪問其它物件的私有資料,特別是例項變數
class c

def initialize

@a=1

endendc=c.new

c.instance_eval

五、class_eval
class_eval可進入類定義體中
c=class.new

c.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.new 

pr.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=lambda 

lam.call

輸出: hello world

lambda不是lambda類的物件,他們是proc類的物件
lam.class

輸出: proc

和所有的proc物件一樣,lambda是閉包;他們隨身攜帶了生成他們的區域性的上下文環境

lambda生成的proc物件和用proc.new生成的物件之間的差別與return有關,lambda中的return從lambda返回,而proc中的return從外圍方法返回

def test_return

l=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

endputs

hello world

#output: 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 更自然,而不是簡單,就像生活...