Ruby 链接如何工作?

发布于 2024-10-15 18:49:30 字数 302 浏览 5 评论 0原文

为什么你可以链接这个:

"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

Why can you chain this:

"Test".upcase.reverse.next.swapcase

but not this:

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

where

class My_Class 

  def a 
    @b = 1 
  end 

  def b
    @b = @b + 2 
  end 

  def c 
    @b = @b -72 
  end

end

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

又爬满兰若 2024-10-22 18:49:30

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 方法还需要返回 self< /code> 因为 c 方法仅在 MyClass 类的实例上可用。在此示例中,c 返回什么并不重要,因为它是链的末尾。它可以返回 self,但不能。薛定谔的方法。在我们打开盒子之前没有人知道。

The upcase, reverse, next and swapcase methods all return String objects and all those methods are for... you guessed it, String objects!

When you call a method (more often than not, like 99.9999% of the time) it returns an object. This object has methods defined on it which can then be called which explains why you can do this:

"Test".upcase.reverse.next.swapcase

You can even call reverse as many times as you like:

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

All because it returns the same kind of object, a String object!

But you can't do this with your MyClass:

x = My_Class.new

x.a.b.c

For that to work, the a method would have to return an object which has the b method defined on it. Right now, that seems like only instances of MyClass would have that. To get this to work you could make the return value of a the object itself, like this:

def a
  @b += 2
  self
end

Extrapolating this, the b method would also need to return self as the c method is available only on instances of the MyClass class. It's not important what c returns in this example, because it's the end of the chain. It could return self, it could not. Schrödinger's cat method. Nobody knows until we open the box.

花落人断肠 2024-10-22 18:49:30

作为对其他答案的支持,此代码:

"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>'

As support for other answers, this code:

"Test".upcase.reverse.next.swapcase

...is almost exactly the same as...

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

....except that my code above has extra variables left over pointing to the intermediary results, whereas the original leaves no extra references around. If we do this with your code:

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'

Using Ruby 1.9's tap method, we can even make this more explicit:

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>'
在风中等你 2024-10-22 18:49:30

函数中的最后一个表达式是其隐式返回值。如果你想链接这样的方法,你需要返回 self 。

例如,您的 a 方法当前返回 1b 不是数字方法。您需要像这样修改它:

def a 
  @b = 1 
  self
end 

The last expression in a function is its implicit return value. You need to return self if you want to chain methods like that.

For example, your a method is currently returning 1. b is not a method for numbers. You'll want to modify it like so:

def a 
  @b = 1 
  self
end 
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文