这段代码与send:[]如何工作?

时间:2015-09-30 00:29:06

标签: ruby methods

以下代码生成9的输出。我理解send只是调用方法:[],但我很困惑参数如何工作。

 x = [1,2,3]
 x.send :[]=,0,4                             #why is x now [4,2,3]
 x[0] + x.[](1) + x.send(:[],2)              # 4 + 2 + 3

第2行和第3行如何运作?

3 个答案:

答案 0 :(得分:4)

Object#send提供了另一种调用方法的方法。

x.send :[]=,0,4  

说,在[]=上调用x方法,并传递参数04,它相当于:

x[0] = 4

名称send是因为在Ruby中,通过向对象发送消息来调用方法。该消息包含方法的名称以及方法可能需要的参数。这个想法来自SmallTalk。

答案 1 :(得分:4)

x.send(:[]=, 0, 4)

相同*
x.[]=(0, 4) 

具有

的语法糖
x[0] = 4

应该熟悉其他语言。 括号当然是可选的。

.send.public_send种类的优点是调用方法不必硬编码 - 它可以来自变量。

所有这些都与ruby的面向对象范式一致:对象通过发送消息相互通信,消息触发代码执行。

*差不多,#send也会调用私有方法

答案 2 :(得分:3)

第2行是

x.send :[]=,0,4

这基本上是写这个的奇特方式:

x[0] = 4

(调用send允许你调用私有方法,这是两种语法之间的一个区别。另外,一个对象可以想象地覆盖send方法,这会破坏第一种语法。 )

因此,第2行具有将4写入数组中的第一个点的效果。

现在在第3行,我们看到我们正在加起来三件事。以下列出了我们要添加的内容:

  • x[0] - 第一个元素
  • x.[](1) - 访问元素的另一种语法,用于访问第二个元素。此语法是传统的方法调用,其方法的名称恰好是[]
  • x.send(:[], 2) - 这显示了Ruby的另一个特性,即send方法。它访问第三个元素。

所以结果将是9,因为第三行添加了数组的第一,第二和第三个元素。

这些例子似乎说明了Ruby语言设计的一个有趣点。具体来说,数组访问是作为方法调用实现的。写入数组的首选语法是x[0] = 4,读取的首选语法是x[0],因为该语法对于来自许多不同语言的程序员来说是熟悉的。但是,从数组读取和写入实际上是使用引擎下的方法调用实现的,这就是为什么可以使用一些看起来更像传统方法调用的其他语法。

传统方法调用如下所示:object.foo(arg1, arg2, arg3, ...)

上面显示的send内容是Ruby的一个有用功能,它允许您使用符号指定要调用的方法,而不是强制您键入确切的名称。它还允许您调用私有方法。