Основное различие между send, __send__
и public_send заключается в следующем.
- send и
__send__
технически аналогичны используемым для вызова метода Object, но основное отличие заключается в том, что вы можетепереопределить метод отправки без какого-либо предупреждения, и при переопределении __send__
появляется предупреждающее сообщение
предупреждение: переопределение __send__
может вызвать серьезные проблемы
Это связано с тем, что во избежание конфликтов, особенно в гемах или библиотеках, когда контекст, в котором он будет использоваться, неизвестен, всегда используйте __send__
вместо send.
Разница между send (или
__send__
) и public_send заключается в том, что send /
__send__
может вызывать приватные методы объекта, а public_send не может.
class Foo
def __send__(*args, &block)
"__send__"
end
def send(*args)
"send"
end
def bar
"bar"
end
private
def private_bar
"private_bar"
end
end
Foo.new.bar #=> "bar"
Foo.new.private_bar #=> NoMethodError(private method 'private_bar' called for #Foo)
Foo.new.send(:bar) #=> "send"
Foo.new.__send__(:bar) #=> "__send__"
Foo.new.public_send(:bar) #=> "bar"
Foo.new.send(:private_bar) #=> "send"
Foo.new.__send__(:private_bar) #=> "__send__"
Foo.new.public_send(:private_bar) #=> NoMethodError(private method 'private_bar' called for #Foo)
В конце попытайтесь использовать public_send, чтобы избежать прямого вызова приватного метода вместо использования __send__ или send.