Ruby发送vs __send__

jay*_*del 145 ruby syntax

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

class Foo
  def bar?
    true
  end
end

foo = Foo.new
foo.send(:bar?)
foo.__send__(:bar?)
Run Code Online (Sandbox Code Playgroud)

有人对此有任何想法吗?

sep*_*p2k 233

某些类(例如标准库的套接字类)定义了自己的send方法,与之无关Object#send.因此,如果您想使用任何类的对象,您需要使用__send__安全的一面.

现在这就留下了问题,为什么存在send而不仅仅是__send__.如果只有__send__名称send可以被其他类使用而没有任何混淆.其原因在于,send存在第一,只是后来人们意识到,名称send也可能有益地在其他情况下使用,所以__send__加入(这与发生同样的事情idobject_id方式).

  • 此外,[BasicObject](http://ruby-doc.org/core/BasicObject.html)(在Ruby 1.9中引入)只有`__send__`,而不是`send`. (7认同)

Thi*_*ira 31

如果你真的需要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
Run Code Online (Sandbox Code Playgroud)

如果覆盖__send__,Ruby将发出警告:

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

覆盖有用的一些情况send是该名称是合适的,如消息传递,套接字类等.


And*_*imm 9

__send__ 存在,所以它不会被意外覆盖.

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


Bor*_*cky 6

除了别人已经告诉你,什么归结为说,send__send__是同一方法的两个别名,你可能有兴趣在第三,somwhat不同的可能性,这是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
Run Code Online (Sandbox Code Playgroud)

更新:由于红宝石2.1,Module#includeModule#extend方法成为公开的,因此上面的例子将不再工作.