2010-04-02 6 views
15

Il peut ne pas être si évident comment répondre à? travaille à ruby. Considérez que:répondez à? et méthodes protégées


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? 

Donc, si 'obj' répond à protected_method nous devrions nous attendre

obj.protected_method 

ne pas soulever une exception, ne devrait pas nous?

... mais il soulève évidemment

Documentation souligne que l'appel respond_to? avec 2 arguments à true contrôle méthode privée ainsi

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

Et qui est beaucoup plus raisonnable

La question est de savoir comment vérifier si l'objet répond à la méthode publique seulement? Y a-t-il une solution meilleure que cela?

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

Répondre

8

Il est en débat si respond_to? devrait rechercher des méthodes protégées ou non (vérifier this issue)

Matz a déclaré qu'il va probablement changer dans Ruby 2.0.

Notez certaines classes peuvent utiliser #method_missing et se spécialiser #respond_to? (ou mieux en spécifier un #respond_to_missing? dans Ruby 1.9.2+), auquel cas votre obj.methods.include? ne sera pas fiable.

+0

Il est difficile pour moi de comprendre le japonais traduit mais de toute façon bon de savoir que le noyau de rubis considère ce problème. Au moins un peut utiliser obj.class.public_method_defined? (: Protected_method) et cela fonctionne comme prévu mais ne traitera pas les méthodes singleton, donc je considère plutôt que la solution de contournement n'est pas la vraie solution – mlomnicki

+0

Réponse mise à jour avec les informations mises à jour –

11

De l'documentation:

Renvoie true si obj répond à la méthode donnée. Privé et méthodes protégées sont inclus dans la recherche que si le second paramètre évalue true

Lorsque la question a été écrit (Ruby 1.8.7):

Renvoie true si obj répond à la méthode donnée. Les méthodes privées sont incluses dans la recherche uniquement si le deuxième paramètre optionnel est évalué à vrai.

+1

La question est de 2010 À l'époque, dans Ruby 1.8.7, les docs déclaraient que: "renvoie true> si obj répond à la méthode donnée Les méthodes privées ne sont incluses dans la recherche que si le deuxième paramètre optionnel est vrai." – steenslag

+1

Encore une réponse précieuse. Je viens de découvrir ce bug curieux lors de la mise à niveau d'un ancien projet de Ruby '1.8.7' à Ruby' 2.1.1'. –

+0

C'est sur [ruby-doc.org] (http://ruby-doc.org/core-2.2.1/Object.html#method-i-respond_to-3F) maintenant. –

Questions connexes