9

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

我的问题是以下示例的“引擎盖下”的区别是什么?

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

2 回答 2

10

来自精美手册

发送(符号 [,args...])→ obj
发送(字符串 [,args...])→ obj

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

instance_eval

instance_eval(string [, filename [, lineno]] ) → obj
instance_eval {| | 块 } → 对象

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

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

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

您可能还感兴趣Object#public_send并且BasicObject#__send__

于 2013-08-04T21:24:04.313 回答
9

无论你能做什么send都是instance_eval. 也就是说, to 的参数send必须是单个方法(及其参数),而 to 的参数instance_method是任意代码。所以只要你有send,你可以用 重写它instance_eval,但反之则不行。

但是,从性能上讲,它比执行时不需要额外的解析send要快得多,而需要解析整个参数。instance_evalsendinstance_eval

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

于 2013-08-04T21:57:36.567 回答