Project

General

Profile

Bug #3350

Protected methods & documentation

Added by marcandre (Marc-Andre Lafortune) almost 9 years ago. Updated about 8 years ago.

Status:
Closed
Priority:
Normal
Target version:
ruby -v:
trunk
Backport:
[ruby-core:30449]

Description

=begin
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 false, the
  • instance methods in mod 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 obj.
  • If the optional all parameter is true, the list will include
  • methods in modules included in obj.
    • * 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
  • obj. This will include all the methods accessible in
  • obj's ancestors. * =end

History

#1

Updated by mame (Yusuke Endoh) almost 9 years ago

=begin
Hi,

2010/5/27 Marc-Andre Lafortune redmine@ruby-lang.org:

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

Agreed. It is more honest.

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

Because whether protected methods can be called are context-sensitive.
Consider this:

class X
def protected_method; end
protected :protected_method
def foo
X.new.protected_method # succeed to call
X.new.methods.include?(:protected_method) #=> true (as expected)
end
end
X.new.foo

If Object#methods returns only public methods, the above expectation
is not satisfied.

Object#methods may be also context-sensitive (IOW, Object#methods
returns different results depending on where it is called), but the
behavior is more difficult (for me) to understand than current one.

--
Yusuke Endoh mame@tsg.ne.jp

=end

#2

Updated by mame (Yusuke Endoh) almost 9 years ago

  • Assignee set to marcandre (Marc-Andre Lafortune)

=begin
Hi,

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

No objection. Please commit it.

--
Yusuke Endoh mame@tsg.ne.jp
=end

#3

Updated by marcandre (Marc-Andre Lafortune) almost 9 years ago

  • Status changed from Open to Closed
  • % Done changed from 0 to 100

=begin
This issue was solved with changeset r28379.
Marc-Andre, thank you for reporting this issue.
Your contribution to Ruby is greatly appreciated.
May Ruby be with you.

=end

Also available in: Atom PDF