我理解some_instance.send
的概念,但我試圖弄清楚爲什麼你可以這樣調用這兩種方式。 Ruby Koans暗示除了提供很多不同的方法來做同樣的事情之外,還有一些原因。以下是兩種使用示例:紅寶石發送vs __send__
class Foo
def bar?
true
end
end
foo = Foo.new
foo.send(:bar?)
foo.__send__(:bar?)
任何人對此有什麼想法?
我理解some_instance.send
的概念,但我試圖弄清楚爲什麼你可以這樣調用這兩種方式。 Ruby Koans暗示除了提供很多不同的方法來做同樣的事情之外,還有一些原因。以下是兩種使用示例:紅寶石發送vs __send__
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__
(這是由用方式和id
發生object_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__
,紅寶石會發出警告:
警告:重新定義`__send__」可能 導致嚴重問題
某些情況下,覆蓋send
將會是合適的名稱,比如message pas唱歌,插座類等
__send__
存在,所以它不能被意外覆蓋。
至於爲什麼send
存在:我不能代表任何人說話,但object.send(:method_name, *parameters)
看起來比object.__send__(:method_name, *parameters)
更好,所以我用send
,除非我需要使用__send__
。
除了別人已經告訴你,什麼歸結爲說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
更新:由於紅寶石2.1,Module#include
和Module#extend
方法成爲公共的,所以上面的例子將不再工作。
此外,[BasicObject](http://ruby-doc.org/core/BasicObject.html)(在Ruby 1.9中引入)只有`__send__`,而不是`send`。 – 2014-08-10 23:50:31
很好的答案。可能會更好,如果它提到`public_send`,這通常比`send`更適合。 – 2016-03-04 00:48:39