为什么你可以链接这个:
"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
、和方法都返回对象upcase
,所有这些方法都是为了……你猜对了,对象!reverse
next
swapcase
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
方法还需要返回self
,因为该c
方法仅在MyClass
类的实例上可用。在这个例子中返回什么并不重要c
,因为它是链的末端。它可以返回self
,它不能。薛定谔的猫法。在我们打开盒子之前没有人知道。
作为对其他答案的支持,此代码:
"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>'
函数中的最后一个表达式是它的隐式返回值。self
如果你想链接这样的方法,你需要返回。
例如,您的a
方法当前正在返回1
. b
不是数字的方法。您需要像这样修改它:
def a
@b = 1
self
end