send和instance_eval之间的Ruby区别?

Posted

技术标签:

【中文标题】send和instance_eval之间的Ruby区别?【英文标题】:Ruby difference between send and instance_eval? 【发布时间】:2013-08-05 12:21:41 【问题描述】:

我知道 send 接受带有参数的字符串或符号,而 instance_eval 接受字符串或块,并且在给定接收器的情况下,它们的区别可能很明显。

我的问题是以下示例的“幕后”区别是什么?

1234.send 'to_s'               # '1234'
1234.instance_eval 'to_s'      # '1234'

【问题讨论】:

【参考方案1】:

来自fine manual:

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

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

对于instance_eval

instance_eval(string [, filename [, lineno]] ) → objinstance_eval | |块 → obj

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

所以send 执行一个方法,而instance_eval 执行任意代码块(作为字符串或块),其中self 设置为您正在调用instance_eval 的对象。

在您的情况下,没有太大区别,因为您传递给 instance_eval 的字符串只是一个方法。主要区别在于,任何阅读您的代码的人(包括六个月后的您)都会想知道为什么您使用instance_eval 来调用单个方法。

您可能还对Object#public_sendBasicObject#__send__ 感兴趣

【讨论】:

太好了,我已经想知道为什么我有一个 instance_eval 的单一方法。【参考方案2】:

你可以用send 做的任何事情都是instance_eval 的一个真子集。也就是说,send 的参数必须是单个方法(及其参数),而instance_method 的参数是任意代码。所以只要你有send,你就可以用instance_eval重写它,反之则不行。

但是,在性能方面,sendinstance_eval 快得多,因为执行 send 不需要额外的解析,而 instance_eval 需要解析整个参数。

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

【讨论】:

以上是关于send和instance_eval之间的Ruby区别?的主要内容,如果未能解决你的问题,请参考以下文章

201707《Ruby元编程》

「译」懂点那啥编译

在 Ruby 中用 ':public' 调用 'send' 的含义

ruby #send示例

ruby #send示例

python中ruby obj.send的等价物