在Ruby中发送方法
我刚刚阅读了Ruby中send
,在查看这段代码的时候,我仍然感到困惑(这是来自一个测验,但是它的过期截止date)
x = [1,2,3] x.send :[]=,0,2 x[0] + x.[](1) + x.send(:[],2)
我明白,第一行为x分配一个数组,然后我不明白是什么:[] = ,0,2
做到了,我不明白为什么发送需要在那里我没有得到什么x.[](1)
做和x.send(:[],2)在最后一行
我真的很困惑,我只是不能在网上find这个信息。
我发现发送了什么,但是我仍然有点困惑,并且对这个代码整体有点困惑。
首先,像[]
(数组索引)和[]=
类的东西只是Ruby中的方法。 x
是一个Array
,而数组有一个[]=
方法,它接受两个参数,一个索引和一个值来设置。
使用send
可以让任意parameter passing一个任意的“消息”(方法调用)到对象。
您可以调用x.send :sort
,例如,将“sorting”消息发送到数组。 sorting不需要任何参数,所以我们不必传递任何额外的东西。
另一方面, x#[]=
接受两个参数。 其方法可以认为是这样的:
def []=(index, value) self.set_value_at_index(index, value) end
所以,我们可以用send :[]=, 0, 2
来调用它,就像调用x[0] = 2
。 整洁,嗯?
在Ruby中, a[0] = 2
实际上是a.[]=(0, 2)
语法糖。
知道这一点,这就是你的第二行所做的事情 – 正如你正确猜测的那样,它使用元编程调用带有两个参数的[]=
方法。
这对你的第三行是一样的: a[0]
是Ruby中的语法糖,用于x.[](0)
。
以下代码与您的示例相当简单:
x = [1, 2, 3] x[0] = 2 x[0] + x[1] + x[2]
别担心 在这些情况下Ruby可能有点棘手。 让我们逐行检查代码:
x = [1,2,3] x.send :[]=,0,2 x[0] + x.[](1) + x.send(:[],2)
第一行
第一行很清楚:它为x分配了一个由三个元素组成的数组。 就是这个。
第二行
第二行调用x
传递一个符号的Object#send
方法(记住,所有以…开头的符号都是ruby中的符号) :[]=
, 0
(一个Fixnum
)和2
(另一个Fixnum
)。
现在你只需要看一下发送方法是什么(就像你说过的那样):
调用由符号标识的方法,传递任何指定的参数
这意味着它将调用由:[]=
标识的方法,并将0
和2
传递给它。 现在我们来看一下Array#[]=
方法。 这个方法定义(如果你需要的话可以重载 )是:
class Array # ... def []=(a, b) # ... end end
这个方法是通过send
作为x.[]=(0, 2)
来调用的,如果你问我的话这是非常难看的。 这就是为什么Ruby定义了一个语法糖的版本: x[0] = 2
,一般来说:
x.[]=(a, b) --> x[a] = b
在Array
情况下,我们也有以下几点:
x.[](a) --> x[a]
在这两种情况下,您都可以在特定的上下文中自由调用任何版本。
第三行
现在第三行也是最后一行:
x[0] + x.[](1) + x.send(:[],2)
事情变得非常棘手。 我们把它分成:
-
x[0]
-
x.[](1)
-
x.send(:[], 2)
第一个很简单。 它返回数组的第一个元素。
第二个是我们之前看到的语法糖,基本上可以转换成x[1]
,它返回数组的第二个元素。
第三个使用Object#send
来调用方法[]
传递2
给它。 这意味着它调用x.[](2)
这意味着x[2]
。
结论
代码
x = [1,2,3] x.send :[]=,0,2 x[0] + x.[](1) + x.send(:[],2)
可以转换使用:
x.send(:[]=, a, b) --> x.[]=(a, b) x.send(:[], a) --> x.[](a) x.[]=(a, b) --> x[a] = b x.[](a) --> x[a]
至:
x = [1,2,3] x[0] = 2 x[0] + x[1] + x[2]
可以简化为:
2 + 2 + 3
这导致:
7
send
是一种在ruby中实现reflection调用的方法。 因此这条线:
x.send :[]=,0,2
相当于:
x[0] = 2
你这样读:方法的名称是符号(在你的情况下[]=
),然后传递参数 – 0和2。
x [0] + x [1] + x [2] = 2 + 2 + 3 = 7我想这一定是答案