Je sais en Ruby que je peux utiliser respond_to?
pour vérifier si un objet a une certaine méthode.
Mais, étant donné la classe, comment puis-je vérifier si l'instance a une certaine méthode?
c'est-à-dire quelque chose comme
Foo.new.respond_to?(:bar)
Mais j'estime qu'il doit y avoir un meilleur moyen que d'instancier une nouvelle instance.
Je ne sais pas pourquoi tout le monde suggère que vous devriez utiliser instance_methods
et include?
lorsque method_defined?
fait le travail.
class Test
def hello; end
end
Test.method_defined? :hello #=> true
Vous pouvez utiliser method_defined?
comme suit:
String.method_defined? :upcase # => true
Beaucoup plus facile, portable et efficace que le instance_methods.include?
que tout le monde semble suggérer.
N'oubliez pas que vous ne saurez pas si une classe répond dynamiquement à certains appels avec method_missing
, par exemple en redéfinissant respond_to?
, ou depuis Ruby 1.9.2 en définissant respond_to_missing?
.
En réalité, cela ne fonctionne pas pour les objets et les classes.
Cela fait:
class TestClass
def methodName
end
end
Donc, avec la réponse donnée, cela fonctionne:
TestClass.method_defined? :methodName # => TRUE
Mais cela ne marche PAS:
t = TestClass.new
t.method_defined? : methodName # => ERROR!
Donc, je l'utilise pour les classes et les objets:
Des classes:
TestClass.methods.include? 'methodName' # => TRUE
Objets:
t = TestClass.new
t.methods.include? 'methodName' # => TRUE
La réponse à " Étant donné une classe, voir si instance a method (Ruby) " est préférable. Apparemment, Ruby a cette fonction intégrée et je l’ai ratée. Ma réponse est laissée pour référence, peu importe.
Les classes Ruby répondent aux méthodes instance_methods
et public_instance_methods
. En Ruby 1.8, le premier répertorie tous les noms de méthodes d'instance dans un tableau de chaînes et le second le limite aux méthodes publiques. Le second comportement correspond à ce que vous voudriez probablement, puisque respond_to?
se limite également aux méthodes publiques par défaut.
Foo.public_instance_methods.include?('bar')
En Ruby 1.9, cependant, ces méthodes renvoient des tableaux de symboles.
Foo.public_instance_methods.include?(:bar)
Si vous envisagez de le faire souvent, vous voudrez peut-être étendre Module
pour inclure une méthode de raccourci. (Cela peut sembler étrange d’attribuer ceci à Module
au lieu de Class
, mais puisque c’est là que vivent les méthodes instance_methods
, il est préférable de rester en ligne avec ce modèle.)
class Module
def instance_respond_to?(method_name)
public_instance_methods.include?(method_name)
end
end
Si vous souhaitez prendre en charge à la fois Ruby 1.8 et Ruby 1.9, vous pouvez également ajouter la logique permettant de rechercher des chaînes et des symboles.
Pas sûr que ce soit la meilleure façon, mais vous pouvez toujours le faire:
Foo.instance_methods.include? 'bar'
Essayez Foo.instance_methods.include? :bar
Si vous vérifiez si un objet peut répondre à une série de méthodes, vous pouvez procéder comme suit:
methods = [:valid?, :chase, :test]
def has_methods?(something, methods)
methods & something.methods == methods
end
le methods & something.methods
joindra les deux tableaux sur leurs éléments communs/correspondants. quelque chose.les méthodes incluent toutes les méthodes que vous recherchez, ça va être des méthodes égales. Par exemple:
[1,2] & [1,2,3,4,5]
==> [1,2]
alors
[1,2] & [1,2,3,4,5] == [1,2]
==> true
Dans cette situation, vous voudriez utiliser des symboles, car lorsque vous appelez. Méthodes, il retourne un tableau de symboles et si vous utilisez ["my", "methods"]
, il retourne false.
Je pense qu'il y a quelque chose qui ne va pas avec method_defined?
dans Rails. Cela peut être incohérent ou quelque chose comme ça, donc si vous utilisez Rails, il est préférable d’utiliser quelque chose de attribute_method?(attribute)
.
" le test de method_defined? sur les classes ActiveRecord ne fonctionne pas avant une instanciation " est une question sur l'incohérence.
class Foo
def self.fclass_method
end
def finstance_method
end
end
foo_obj = Foo.new
foo_obj.class.methods(false)
=> [:fclass_method]
foo_obj.class.instance_methods(false)
=> [:fclass_method]
J'espère que cela vous aide!
klass.instance_methods.include :method_name
ou "method_name"
, selon la version de Ruby, je pense.
Dans mon cas de travail avec Ruby 2.5.3, les phrases suivantes ont parfaitement fonctionné:
value = "hello world"
value.methods.include? :upcase
Il retournera une valeur booléenne true ou false.