Почему я могу получить доступ к частному использованию / использованию защищенных методов Object#send в Ruby?

Класс

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

Тест .send

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

.send производится

foo
bar
zim
dib
fail

Вопрос

Раздел маркировал "Test Output", ожидаемый результат. Итак, почему я могу получить доступ к частному / защищенному методу просто Object#send?

Возможно, более важный:

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

5
задан Andrew Grimm 27 March 2012 в 23:38
поделиться

1 ответ

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

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

Что касается того, что означают private, protected и public:

  • public методы могут быть вызваны любым отправителем
  • protected методы не могут быть вызваны вне экземпляра класса метода или экземпляра подкласса
  • private методы не могут быть вызваны с явным получателем (за парой исключений, например, методы setter, которые всегда должны иметь явного получателя, и поэтому могут быть вызваны внутри класса таким образом)
8
ответ дан 14 December 2019 в 04:34
поделиться
Другие вопросы по тегам:

Похожие вопросы: