Bug #3350: Protected methods & documentation
http://redmine.ruby-lang.org/issues/show/3350

Author: Marc-Andre Lafortune
Status: Open, Priority: Normal
Category: core, Target version: 1.9.2
ruby -v: trunk

The official doc currently states that Object#methods "returns a list of the names of methods publicly accessible".

Similarly, Module#instance_methods states that it returns "the public methods" of the Module. Note that the doc was modified in r19900, but I feel the wording "instance method that is callable from outside" still implies public only.

The current behavior doesn't fit the doc, since protected methods are also matched:

    class X
      def protected_method; end
      protected :protected_method
    end
    X.new.methods.include?(:protected_method) #=> true
    X.instance_methods.include?(:protected_method) #=> true

The documentation for Module#method_defined? on the other states it matches public and protected methods.

Should I change the doc to reflect the current behavior, as per the patch below?

I'm asking in part because I lack experience with protected methods and I am surprised by the fact that protected methods are matched by these "default" methods.

The fact that Object#respond_to? also matches protected is even less practical since there is no "public-only" equivalent. I might be mistaken, but I believe that the only way of knowing if obj responds publicly to :foo is to do something like

    publicly_responds = obj.public_method(:foo) rescue false

I dislike the fact that   obj.respond_to?(:foo) && obj.foo   might raise a NoMethodError.

It looks like this was discussed a in [ruby_dev:40461], but I don't know the outcome.

I'm curious: what examples exist where one would want to match public and protected methods but not private ones?

Matz, is there any chance the handling of #respond_to?, #methods, etc..., with regards to protected methods will change (in 1.9.2 or later)?

--
Marc-André


diff --git a/class.c b/class.c
index c586f7a..683fa7b 100644
--- a/class.c
+++ b/class.c
@@ -865,8 +865,8 @@ class_instance_method_list(int argc, VALUE *argv, VALUE mod, int (*func) (ID, lo
  *  call-seq:
  *     mod.instance_methods(include_super=true)   -> array
  *
- *  Returns an array containing the names of instance methods that is callable
- *  from outside in the receiver. For a module, these are the public methods;
+ *  Returns an array containing the names of the public and protected instance
+ *  methods in the receiver. For a module, these are the public and protected methods;
  *  for a class, they are the instance (not singleton) methods. With no
  *  argument, or with an argument that is <code>false</code>, the
  *  instance methods in <i>mod</i> are returned, otherwise the methods
@@ -954,6 +954,7 @@ rb_class_public_instance_methods(int argc, VALUE *argv, VALUE mod)
  *  Returns an array of the names of singleton methods for <i>obj</i>.
  *  If the optional <i>all</i> parameter is true, the list will include
  *  methods in modules included in <i>obj</i>.
+ *  Only public and protected singleton methods are returned.
  *
  *     module Other
  *       def three() end
diff --git a/object.c b/object.c
index a7f05a1..351d16f 100644
--- a/object.c
+++ b/object.c
@@ -1755,7 +1755,7 @@ rb_mod_const_defined(int argc, VALUE *argv, VALUE mod)
  *  call-seq:
  *     obj.methods    -> array
  *
- *  Returns a list of the names of methods publicly accessible in
+ *  Returns a list of the names of public and protected methods of
  *  <i>obj</i>. This will include all the methods accessible in
  *  <i>obj</i>'s ancestors.
  *


----------------------------------------
http://redmine.ruby-lang.org