Search code examples
rubyencapsulationaccess-specifier

respond_to? and protected methods


It may not be so obvious how respond_to? works in ruby. Consider that:


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's pretty obvious
obj.respond_to?(:private_method)
# false - as expected
obj.respond_to?(:protected_method)
# true - WTF?

So if 'obj' responds to protected_method we should expect

obj.protected_method

not to raise an exception, shouldn't we?

...but it raises obviously

Documentation points that calling respond_to? with 2nd argument set to true check private method as well

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

And that's far more reasonable

So the question is how to check if object responds to public method only? Is there a solution better than that?

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

Solution

  • It is under debate if respond_to? should look for protected methods or not (check this issue)

    Matz has stated that it will probably change in Ruby 2.0.

    Note some classes might use #method_missing and specialize #respond_to? (or better by specify a #respond_to_missing? in Ruby 1.9.2+), in which case your obj.methods.include? will not be reliable.