2009-09-07 61 views
2

在這個例子中,從Ruby編程語言(第270頁),我很困惑,爲什麼上示例代碼的最後一行instance_eval方法定義了類方法稱爲String.empty需要與反思例如幫助從「Ruby編程語言」

當您要定義實例方法時,是否使用class_eval來定義類方法,instance_eval

o.instance_eval("@x") # Return the value of o's instance variable @x 

# Define an instance method len of String to return string length 
String.class_eval("def len; size; end") 

# Here's another way to do that 
# The quoted code behaves just as if it was inside "class String" and "end" 
String.class_eval("alias len size") 

# Use instance_eval to define class method String.empty 
# Note that quotes within quotes get a little tricky... 
String.instance_eval("def empty; ''; end") 

回答

7

你不使用class_eval定義 類的方法,當 要定義一個實例方法instance_eval

不幸的是,它並不那麼簡單。

首先仔細看看class_eval正在做什麼的例子。 class_eval是一種來自Ruby的module class的方法,因此可以在任何類或模塊上調用。當您使用String.class_eval時,您正在評估課程背景下的給定代碼。即當你編寫String.class_eval("def len; size; end")時,就好像你重新打開了類並輸入了傳遞給class_eval例如

class String 
    def len 
    size 
    end 
end 

因此增加使用class_eval你會寫String.class_eval("def self.empty; ''; end")具有相同的效果類方法:

class String 
    def self.empty 
    '' 
    end 
end 

instance_eval在Ruby的Object class定義所以可用任何Ruby對象。在一般情況下,它可用於將方法添加到特定實例。例如如果我們有一個字符串str,並說:

str.instance_eval("def special; size; end") 

,那麼這將別名任何其他String對象specialsize只是str但不是:

irb(main):019:0> "other".special 
NoMethodError: undefined method `special' for "other":String 
     from (irb):19 

爲了理解正在發生的事情與字符串。 instance_eval記住類String本身就是一個對象(類Class的一個實例),並且每個類定義了一個單例實例對象。當您使用String.instance_eval時,您正在評估String實例對象上下文中的給定代碼。即等同於重新打開字符串的元類並鍵入傳遞的代碼

class String 
    class << self 
    def empty 
     '' 
    end 
    end 
end 
1

這是總的主題:

使用ClassName.instance_eval定義 單方法。

使用ClassName.class_eval來定義 實例方法。

post有一個非常整潔的解釋,給它一個鏡頭...