Bug #14252
closedRefined Method Visibility Lost with Dynamic Dispatch and Reflection
Description
Consider the following simple objects, one with a protected class method and another with a public class method calling on the protected method. This is accomplished using a refinement that marks the method as public on the singleton class of the original object.
class Protected class << self protected def print :protected end end end module Publicize refine Protected.singleton_class do public :print end end class Public using Publicize def self.print Protected.public_methods.include?(:print) # false Protected.protected_methods.include?(:print) # true Protected.print # works Protected.public_send(:print) # fails end end Public.print This works perfectly well for the static Protected.print call, but has a number of surprises when trying to do anything more advanced. Namely:
- Attempting to call the method with refined visibility raises a
NoMethodError - The method appears in the
protected_methodslist of the original object - The method does not appear in the
public_methodslist of the original object
As a user, I would expect all those things to be not the case, since, if I opened the class directly and changed the visibility of the method, those three items would no longer be true.
Updated by shugo (Shugo Maeda) almost 8 years ago
sonnym (Sonny Michaud) wrote:
This works perfectly well for the static
Protected.printcall, but has a number of surprises when trying to do anything more advanced. Namely:
- Attempting to call the method with refined visibility raises a
NoMethodError- The method appears in the
protected_methodslist of the original object- The method does not appear in the
public_methodslist of the original object
Reflection APIs do not honor refinements.
If you believe they should, please create a feature ticket for each API family.
Refinements were enabled in Kernel#send by #11476, so it may be reasonable to
enable refinements in Kernel#public_send.
Updated by sonnym (Sonny Michaud) almost 8 years ago
I, personally, do not care so much about the reflection APIs, as I was just using them to confirm what I thought was happening, but I would like to at least see Kernel#public_send act similarly to Kernel#send, so I think it makes sense to scope this issue to that change.
Updated by jeremyevans0 (Jeremy Evans) over 6 years ago
- Status changed from Open to Closed
Ruby 2.6.0 started honoring refinements in Kernel#public_send.