2012-12-27 94 views
3

我對Ruby的Koans工作about_message_passing.rb並得到了工作method_missing的代碼如下:紅寶石Koans關於通過「發送」消息塊和參數

def method_missing(method_name, *args, &block) 
    @messages << method_name 
    @object.__send__(method_name, *args, &block) 
end 

此代碼似乎工作,但我不很明白,爲什麼在參數中需要圖示和&是需要的塊。

如果我定義了一個方法,我知道*和&分別用於表示一個數組參數和塊參數,但是它們與send方法一起用於在對象上調用方法時意味着什麼?

回答

9

我會一次拿這一個。完全脫離method_missing,因爲這隻會讓人感到困惑。這實際上完全沒有關係。


splat *有2件事。在方法定義的參數中,它將多個參數吸收到一個數組中。當在方法調用中使用時,它將數組劃分爲單獨的參數。使用這兩種方法可以將任意數量的參數轉發給其他方法。

def foo(*args) 
    bar(*args) 
end 

def bar(a, b, c) 
    puts a 
    puts b 
    puts c 
end 

foo(1,2,3) # prints 1, 2 and then 3 

由於您基本上是轉發所有參數,這是相同的模式。


&用於塊參數。每個方法調用都可以有其中的一個,它是掛起的塊。這是一個特殊的論點,因爲它不直接引入論證。通過捕獲添加&someblock作爲方法定義中的最後一個參數,可以將該塊捕獲到變量。

然後,您可以使用相同的語法在方法調用中傳遞一個塊。

def foo(&block) 
    bar(&block) 
end 

def bar 
    yield 
end 

foo { puts 'hello' } # prints hello 

這允許您將掛塊傳遞給另一個方法,而不用調用它。它並不總是需要的,因爲通常只需使用yield來執行通過的任何塊。但是,如果除了執行它之外還想執行某些操作,則需要捕獲對塊本身的引用。


所以,如果你把這些兩件事情,你得到的終極方法轉發器。您可以捕獲所有任意數量的參數以及任何掛起的塊,然後將其發送給其他方法。

# forwards everything to the method `bar` 
def foo(*args, &block) 
    bar(*args, &block) 
end 

最後,send只是一個方法。它需要一個方法的名稱,後面跟着任意數量的參數(不是數組),並且可以選擇處理掛起的塊。

換句話說:

foo.send methodName, *args, &block 
+0

注意,圖示並不僅僅適用於方法的參數定義/參數列表。它也適用於塊參數定義/參數列表,*和*賦值。 –

0

據我所知,任何時候你直接通過一個塊,它的語法是& block_name。

另外,Object#send的方法簽名需要無限的參數,而不是數組。所以通過傳遞splatted的值* args,就像你傳遞了逗號分隔的參數一樣。

1

方法定義中的圖示意味着「取所有不匹配的參數並將它們放入一個數組中」(在ruby 1.8中,這總是最後一個參數,但在1.9中可以出現splat)。

在一個方法調用使用它是反向:它意味着藉此陣列和使用它的內容作爲參數

foo(a,b) #call foo with 2 arguments: a and b 
foo([a,b]) #call foo with a single array argument 
foo(*[a,b]) # call foo with 2 arguments: a and b 

&是相似的:在一個方法定義它捕獲塊並把它變成一個proc,但在一個方法調用它將一個proc(或proc像對象 - 任何響應to_proc將做)到該方法的塊

你需要這兩個爲method_missing,因爲(一般)你想通過沿着原始方法調用的所有參數和塊。