Respond_to? и защищенные методы

Возможно, это не так очевидно, как response_to? работает в рубине. Предположим, что:


class A

   def public_method
   end

   protected
   def protected_method
   end

   private
   def private_method
   end

end

obj = A.new
obj.respond_to?(:public_method)
# true - that pretty obvious
obj.respond_to?(:private_method)
# false - as expected
obj.respond_to?(:protected_method)
# true - WTF?

Итак, если "obj" отвечает на protected_method, мы должны ожидать

obj.protected_method

не создавать исключение, не так ли?

... но он явно поднимается

Документация указывает, что вызывает response_to? с 2-мя аргументами, установленными в true check private method, а также

obj.respond_to?(:private_method, true)
# true

И это гораздо разумнее

Итак, вопрос в том, как проверить, отвечает ли объект только на общедоступный метод? Есть ли решение лучше, чем это?

obj.methods.include?(:public_method)
# true
obj.methods.include?(:protected_method)
# false

Ответы

Ответ 1

Обсуждается, следует ли respond_to? искать защищенные методы или нет (отметьте эту проблему)

Мац заявил, что он, вероятно, изменится в Ruby 2.0.

Обратите внимание, что некоторые классы могут использовать #method_missing и специализировать #respond_to? (или лучше указать a #respond_to_missing? в Ruby 1.9.2+), и в этом случае ваш obj.methods.include? не будет надежным.

Ответ 2

Из документации:

Возвращает true, если obj отвечает данному методу. Частные и   защищенные методы включены в поиск, только если необязательный   второй параметр оценивается как true

Когда вопрос был написан (Ruby 1.8.7):

Возвращает true, если obj отвечает данному методу. Частные методы включаются в поиск только в том случае, если дополнительный второй параметр имеет значение true.