なぜこれを連鎖させることができますか:
"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