Project

General

Profile

Actions

Bug #8743

closed

Inconsistent behaviour calling public_methods on class (Plus documentation slightly ambiguous)

Bug #8743: Inconsistent behaviour calling public_methods on class (Plus documentation slightly ambiguous)

Added by stestagg (Steve Stagg) over 12 years ago. Updated about 2 months ago.

Status:
Closed
Assignee:
-
Target version:
-
ruby -v:
ruby 2.1.0dev (2013-08-06 trunk 42401) [x86_64-darwin12.4.0]
Backport:
[ruby-core:<unknown>]

Description

=begin
= Background

I was trying to identify classes on which a specific class method (def self.xx) was actually defined (in the case of multiple levels of inheritance). This currently doesn't seem to be possible, although the docs suggest that calling class.public_methods(false) should do this.

While investigating, I discovered that the behaviour of calling instance.public_methods(false) is not consistent with that of calling class.public_methods(false) [They should be different, of course, but the behaviour should be consistent]. The attached test script highlights this.

= Steps to Reproduce

Run the attached ruby script

= Expected Result

Ideally, all tests pass, but at least test_consistent_behaviour should pass

= Actual Results

test_this_is_what_i_expect, and test_consistent_behaviour both fail.

= Example test output

steves@sapphire ~/s/t/ruby> env RUBYLIB=./lib ./ruby ~/foo.rb
Run options:

Running tests:

[2/5] PublicMethodsTest#test_consistent_behaviour = 0.00 s

  1. Failure:
    PublicMethodsTest#test_consistent_behaviour [/Users/steves/foo.rb:73]:
    Differences: bar. "bar" is inherited from A, but doesn't include methods inherited from Object!

[5/5] PublicMethodsTest#test_this_is_what_i_expect = 0.00 s
2) Failure:
PublicMethodsTest#test_this_is_what_i_expect [/Users/steves/foo.rb:59]:
Differences: allocate, new, superclass.

Finished tests in 0.005998s, 833.6112 tests/s, 2834.2781 assertions/s.
5 tests, 17 assertions, 2 failures, 0 errors, 0 skips

ruby -v: ruby 2.1.0dev (2013-08-06 trunk 42401) [x86_64-darwin12.4.0]

Seen on ruby 1.8, 2.0 and trunk
=end


Files

foo.rb (2.22 KB) foo.rb stestagg (Steve Stagg), 08/06/2013 09:24 PM

Updated by jeremyevans0 (Jeremy Evans) over 6 years ago Actions #1 [ruby-core:93734]

  • Status changed from Open to Closed
  • Backport deleted (1.9.3: UNKNOWN, 2.0.0: UNKNOWN)

The reason for this interesting behavior is because the documentation for include flag (2nd argument) for public_methods is not precise. It states:

If the all parameter is set to false, only those methods
in the receiver will be listed.

However, the behavior is actually:

If the all parameter is set to false, the list will include methods
in ancestors, stopping after a non-singleton class is encountered
(including the methods from the non-singleton class).

The lookup process for Empty.public_methods(false) is something like this:

  • Empty.singleton_class # adds no methods
  • Object.singleton_class # adds no methods
  • BasicObject.singleton_class # adds no methods
  • Class # adds 3 methods [:allocate, :superclass, :new]
  • Module # does not get here, as Class is not a singleton class

So that is the reason Empty.public_methods(false) gives you [:allocate, :superclass, :new].

B.public_methods(false) including singleton methods from A is similar:

  • B.singleton_class # adds no methods
  • A.singleton_class # adds 1 method [:bar]
  • Object.singleton_class # adds no methods
  • BasicObject.singleton_class # adds no methods
  • Class # adds 3 methods [:allocate, :superclass, :new]
  • Module # does not get here, as Class is not a singleton class

Which is the reason that Bar.public_methods(false) gives you [:bar, :allocate, :superclass, :new].

I'm not sure it worth updating the documentation to be more precise in this area, but I'm open to suggestions.

Updated by trinistr (Alexander Bulancov) about 2 months ago Actions #2 [ruby-core:124587]

I've been working on some tests using public_methods, and was bitten by this. I think a documentation update is definitely needed. Docs shouldn't straight-up lie.

Though I personally think that Module (or Class?) should just have different implementations of these methods. Current behavior makes some sense for instances, but for classes it's plain weird.

Actions

Also available in: PDF Atom