Почему я могу получить доступ к закрытым / защищенным методам, используя Object # send в Ruby? - PullRequest
5 голосов
/ 25 марта 2010

Класс

class A

  private
  def foo
    puts :foo
  end

  public
  def bar
    puts :bar
  end

  private
  def zim
    puts :zim
  end

  protected
  def dib
    puts :dib
  end
end

экземпляр A

a = A.new

тест

a.foo rescue puts :fail
a.bar rescue puts :fail
a.zim rescue puts :fail
a.dib rescue puts :fail
a.gaz rescue puts :fail

тестовый вывод

fail
bar
fail
fail
fail

. Отправить тест

[:foo, :bar, :zim, :dib, :gaz].each { |m| a.send(m) rescue puts :fail }

. Отправить вывод

foo
bar
zim
dib
fail

Вопрос

Раздел с пометкой «Результат теста» является ожидаемым результатом. Так почему я могу получить доступ к закрытому / защищенному методу просто Object#send?

Возможно, важнее:

В чем разница между public / private / protected в Ruby? Когда использовать каждый? Может ли кто-нибудь предоставить примеры из реальной жизни для использования private и protected?

1 Ответ

8 голосов
/ 25 марта 2010

Технически: потому что send ничего не делает для проверки видимости метода. (Это будет больше работы для этого.)

Философски: Ruby - очень разрешительный язык. Вы уже можете просто открыть класс и сделать любой метод, который вы хотите, публичным. Разработчики языка реализовали send таким образом, что он позволяет переопределить ограничения, обычно накладываемые private. Изначально в Ruby 1.9 было два варианта: private -связывающий send и небезопасный вариант под названием send!, но он, по-видимому, был исключен для обратной совместимости.

Что означает private, protected и public:

  • public методы могут быть вызваны любым отправителем
  • protected методы нельзя вызывать вне экземпляра класса метода или экземпляра подкласса
  • private методы не могут быть вызваны с явным получателем (с несколькими исключениями, такими как методы сеттера, которые всегда должны иметь явный получатель, и поэтому могут вызываться в классе таким образом)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...