Ruby中send和instance_eval的区别是什么?

9

我知道send方法可以带字符串或符号作为参数调用,而instance_eval方法可以接受字符串或块作为参数,并且它们之间的区别可以根据接收者的不同变得明显。

我的问题是下面这个例子的具体实现方式有什么不同?

1234.send 'to_s'               # '1234'
1234.instance_eval 'to_s'      # '1234'
2个回答

11

精细手册得知:

send(symbol [, args...]) → obj
send(string [, args...]) → obj

调用由symbol标识的方法,并传递指定的任何参数[...]当使用字符串标识方法时,字符串会被转换为符号。

对于instance_eval

instance_eval(string [, filename [, lineno]] ) → obj
instance_eval {| | block } → obj

在接收者(obj)上下文中执行包含Ruby源代码的字符串或给定块。为了设置上下文,当代码执行时变量self设为obj,使得该代码可以访问obj的实例变量。

因此,send执行一个方法,而instance_eval则执行代码块(作为字符串或块),并将self设置为调用instance_eval的对象。

在你的情况下,由于你向instance_eval传递的字符串只是一个单一的方法,所以两者并没有太大差别。主要区别在于读取你的代码(包括6个月后的你)的人会想知道为什么你要使用instance_eval来调用单个方法。

您可能也对Object#public_sendBasicObject#__send__感兴趣。


1
太好了,我已经在想为什么我只有一个instance_eval方法。 - Skiptomylu

10

send方法的功能是instance_eval方法的一个子集。简而言之,send方法的参数必须是单个方法(及其参数),而instance_eval方法的参数可以是任意代码。因此,每当您使用send时,都可以使用instance_eval进行重写,但反之则不行。

然而,从性能上来讲,sendinstance_eval更快速,因为执行send时不需要进行额外的解析,而instance_eval需要解析整个参数。

在您的示例中,结果将相同,但第一个方法会运行得更快。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接