2011-02-03 51 views
5

爲什麼會這樣連鎖:Ruby鏈接如何工作?

"Test".upcase.reverse.next.swapcase 

但不是這樣的:

x = My_Class.new 
x.a.b.c 

其中

class My_Class 

    def a 
    @b = 1 
    end 

    def b 
    @b = @b + 2 
    end 

    def c 
    @b = @b -72 
    end 

end 
+0

以下鏈接http://stackoverflow.com/questions/ 3955688 /我如何做調試ruby腳本/ 3955730#3955730可能使您能夠更好地解決Ruby中發生了什麼問題。 – 2011-02-03 01:47:28

+0

哦,所以你認爲我不運行調試? ;) – 2011-02-03 05:42:06

回答

7

upcasereversenextswapcase方法均返回String對象,所有這些方法是......你猜對了,String對象!

當你調用一個方法時(通常是99.9999%的時間),它返回一個對象。這個對象上有定義的方法,然後可以稱爲這就解釋了爲什麼你可以這樣做:

"Test".upcase.reverse.next.swapcase 

,你甚至可以稱之爲reverse多次,只要你喜歡:

"Test".reverse.reverse.reverse.reverse.reverse.reverse.reverse.reverse 

所有,因爲它返回同一種對象,一個String對象!

但你不能做到這一點你MyClass

x = My_Class.new 

x.a.b.c 

對於工作,a方法必須返回其上定義的b方法的對象。現在,這似乎只有MyClass的實例會有。爲了得到這個工作,你可以做的a返回值的對象本身,這樣的:

def a 
    @b += 2 
    self 
end 

推斷這一點,b方法也需要返回selfc方法僅適用於的情況下, MyClass類。在這個例子中,什麼c返回並不重要,因爲它是鏈的結尾。它可能會返回self,它不能。 Schrödinger的方法。沒有人知道,直到我們打開箱子。

5

在函數的最後表達其隱含的返回值。如果你想連鎖那樣的方法,你需要返回self

例如,您的a方法當前返回1b不是數字的方法。你要修改它,像這樣:

def a 
    @b = 1 
    self 
end 
6

至於其他的答案的支持,這樣的代碼:

"Test".upcase.reverse.next.swapcase 

...幾乎完全一樣......

a = "Test" 
b = a.upcase 
c = b.reverse 
d = c.next 
e = d.swapcase 

....除了我上面的代碼有多餘的指向中間結果的變量,而原始文件沒有多餘的引用。如果我們這樣做你的代碼:

x = MyClass.new # x is an instance of MyClass 
y = x.a   # y is 1, the last expression in the a method 
z = y.b   # Error: Fixnums have no method named 'b' 

使用Ruby 1.9的tap方法,我們甚至可以讓這個更明確:

irb> "Test".upcase.tap{|o| p o}.reverse.tap{|o| p o}.next.tap{|o| p o}.swapcase 
#=> "TEST" 
#=> "TSET" 
#=> "TSEU" 
=> "tseu" 

irb> class MyClass 
irb> def a 
irb>  @b = 1 
irb> end 
irb> def b 
irb>  @b += 2 
irb> end 
irb> end 
=> nil 

irb(main):011:0> x = MyClass.new 
=> #<MyClass:0x000001010202e0> 

irb> x.a.tap{|o| p o}.b.tap{|o| p o}.c 
#=> 1 
NoMethodError: undefined method `b' for 1:Fixnum 
from (irb):12 
from /usr/local/bin/irb:12:in `<main>'