objects - Ruby send vs__send__
ruby>= (4)
Algunas clases (por ejemplo, la clase de socket de la biblioteca estándar) definen su propio método de send
que no tiene nada que ver con Object#send
. Entonces, si quieres trabajar con objetos de cualquier clase, necesitas usar __send__
para estar seguro.
Ahora que deja la pregunta, por qué hay send
y no solo __send__
. Si solo __send__
el __send__
del nombre podría ser utilizado por otras clases sin confusión. La razón es que el send
existió primero y solo más tarde se supo que el send
del nombre también podría ser útil en otros contextos, por __send__
se agregó __send__
(es lo mismo que sucedió con id
y object_id
por cierto).
Entiendo el concepto de some_instance.send
pero estoy tratando de averiguar por qué puedes llamar esto en ambos sentidos. Los Ruby Koans implican que hay alguna razón más allá de proporcionar muchas maneras diferentes de hacer lo mismo. Aquí están los dos ejemplos de uso:
class Foo
def bar?
true
end
end
foo = Foo.new
foo.send(:bar?)
foo.__send__(:bar?)
Alguien tiene alguna idea sobre esto?
Aparte de lo que otros ya te dijeron, y lo que se reduce a decir que send
y __send__
son dos alias del mismo método, puede que te interese la tercera posibilidad, algo diferente, que es public_send
. Ejemplo:
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
Actualización: Dado que los métodos de Module#extend
Ruby 2.1, Module#include
y Module#extend
hacen públicos, el ejemplo anterior ya no funcionaría.
Si realmente necesita send
para comportarse como lo haría normalmente, debería usar __send__
, porque no será (no debería) anulado. Usar __send__
es especialmente útil en la metaprogramación, cuando no sabes qué métodos define la clase que se está manipulando. Podría haber send
.
Reloj:
class Foo
def bar?
true
end
def send(*args)
false
end
end
foo = Foo.new
foo.send(:bar?)
# => false
foo.__send__(:bar?)
# => true
Si anula __send__
, Ruby emitirá una advertencia:
advertencia: redefinir `__send__ ''puede causar problemas graves
Algunos casos en los que sería útil sobrescribir el send
serían aquellos en los que ese nombre sea apropiado, como el send
mensajes, las clases de socket, etc.
__send__
existe por lo que no se puede __send__
por accidente.
En cuanto a por qué existe el send
: no puedo hablar por nadie más, pero object.send(:method_name, *parameters)
ve mejor que el object.__send__(:method_name, *parameters)
, entonces uso send
menos que necesite usar __send__
.