2012-01-25 71 views
2

這聽起來很奇怪不是嗎?如何將塊傳遞給名稱以等號結尾的方法?

class Dummy 
    def foo=(value); end 
end 

Dummy.new.foo = 1 { |x| x } # => syntax error 
Dummy.new.foo=(1) { |x| x } # => syntax error 

我試過每一個空白,括號,逗號的排列組合;沒有運氣。我很困惑。我從來不懷疑以'='結尾的方法是特別的。這是一個錯誤?它的目的是?如果打算,爲什麼?有記錄嗎?哪裏?請分享見解。

謝謝

ps。 ruby是1.9.2p290(2011-07-09修訂版32553)[x86_64-darwin11.0.1]

+1

如果您描述了您想要編寫的代碼,以及爲什麼您認爲將塊傳遞給以'= =結尾的方法有意義的原因可能會有所幫助。 – Phrogz

回答

2

=結尾的方法的語法糖確實使它變得特別。你仍然可以做的事情一樣多個參數傳遞給方法,或傳遞塊,但不是在任何漂亮或方便的方式:

class Foo 
    def bar=(a,b=nil) 
    p [a,b] 
    if block_given? 
     yield "hi" 
    else 
     puts "No block" 
    end 
    end 
end 

f = Foo.new 
f.bar = 42 
#=> [42, nil] 
#=> No block 

f.bar = 42, 17 
#=> [[42,17], nil] 
#=> No block 

f.send(:bar=,42,17) do |x| 
    puts "x is #{x.inspect}" 
end 
#=> [42, 17] 
#=> x is "hi" 

另一種方式,這些方法都是特別的是,當與語法糖叫他們的計算結果爲右手值,而不是方法的返回值:

class Foo 
    def bar=(a) 
    return 17 # really explicit 
    end 
end 

f = Foo.new 

x = (f.bar = 42) 
p x 
#=> 42 

x = f.send(:bar=,42) 
p x 
#=> 17 
0

這與其說是方法本身是特殊的,但更多的是用Ruby如何與分配(如foo = bar)交易。首先評估右手側,然後評估左手側並採取適當的行動。如果左側是對象屬性,則調用適當的setter方法。

所以在你的例子:

Dummy.new.foo = 1 { |x| x } 

第一臺紅寶石試圖evalulate 1 { |x| x },這是什麼原因造成的語法錯誤。

Dummy.new.foo=something並不實際上意味着「調用一個名爲foo=方法」,但實際上意味着更多的東西,如「evalualate something,然後確定哪些`Dummy.new.foo是,如果它看起來像一個對象的屬性,添加=的名稱和調用該方法「。這就是爲什麼Dummy.new.foo=Dummy.new.foo =都以相同的方式工作。

可以調用使用send這些方法,並且可以通過塊與此:

Dummy.new.send "foo=", 2 do 
    puts "HI" 
end 

這是因爲send您可以顯式指定要調用的方法。

當然,最終結果是以=結尾的方法似乎有一些您需要注意的「特殊」行爲,但它可能對了解實際發生的情況有用。

相關問題