Ruby发送vs __send__

我理解some_instance.send的概念,但我试图弄清楚为什么你可以调用这两种方式。 Ruby Koans暗示,除了提供很多不同的方法来做同样的事情之外,还有一些原因。 以下是使用的两个例子:

 class Foo def bar? true end end foo = Foo.new foo.send(:bar?) foo.__send__(:bar?) 

任何人有任何想法呢?

有些类(例如标准库的套接字类)定义了自己的send方法,这与Object#send无关。 所以如果你想使用任何类的对象,你需要使用__send__来保证安全。

现在留下了这个问题,为什么有send ,而不仅仅是__send__ 。 如果只有__send__send的名字可以被其他类使用,不会有任何混淆。 之所以这样,是因为send是先存在的,后来才意识到send的名字也可能用在其他的上下文中,所以__send__被添加了(这与idobject_id的方式是一样的)。

如果你真的需要send像往常一样的行为,你应该使用__send__ ,因为它不会(不应该)被覆盖。 使用__send__在元编程中特别有用,当你不知道被操纵的类是什么方法定义的。 它可能会覆盖send

看:

 class Foo def bar? true end def send(*args) false end end foo = Foo.new foo.send(:bar?) # => false foo.__send__(:bar?) # => true 

如果你重载__send__ ,Ruby会发出警告:

警告:重新定义`__send__'可能会导致严重的问题

在某些情况下,重写send将是有用的,比如消息传递,套接字类等。

__send__存在,所以不能被意外覆盖。

至于为什么send存在:我不能说任何人,但object.send(:method_name, *parameters)看起来比object.__send__(:method_name, *parameters)更好object.__send__(:method_name, *parameters) ,所以我使用send除非我需要使用__send__

除了别人已经告诉过你的话,可以归结为send__send__是同一个方法的两个别名,你可能会对第三个有些不同的可能性是public_send感兴趣。 例:

 A, B, C = Module.new, Module.new, Module.new B.include A #=> error -- private method B.send :include, A #=> bypasses the method's privacy C.public_send :include, A #=> does not bypass privacy 

更新:由于Ruby 2.1, Module#includeModule#extend方法变成公共的,所以上面的例子不再工作了。