Obtenir la liste des méthodes d'instance d'une classe

98

J'ai un cours:

class TestClass
  def method1
  end

  def method2
  end

  def method3
  end
end

Comment puis - je obtenir une liste de mes méthodes de cette classe ( method1, method2, method3)?

Vladimir Tsukanov
la source

Réponses:

115

Vous voulez vraiment TestClass.instance_methods, sauf si vous êtes intéressé par ce que TestClasslui-même peut faire.

class TestClass
  def method1
  end

  def method2
  end

  def method3
  end
end

TestClass.methods.grep(/method1/) # => []
TestClass.instance_methods.grep(/method1/) # => ["method1"]
TestClass.methods.grep(/new/) # => ["new"]

Ou vous pouvez appeler methods(pas instance_methods) sur l'objet:

test_object = TestClass.new
test_object.methods.grep(/method1/) # => ["method1"]
Andrew Grimm
la source
3
Hé, tu m'as battu de 47 secondes. +1
Phrogz
2
Quand j'essaye print TestClass.new.instance_methods, j'obtiens cette erreurmy_class.rb:10:in <main>: undefined method instance_methods for #<TestClass:0x96b9d20> (NoMethodError)
Vladimir Tsukanov
Vous n'avez qu'à faire TestClass.new.methods. Peut-être que "ça" était ambigu dans ma réponse.
Andrew Grimm
Notez que sous Ruby 1.9+, le tableau des noms de méthodes sont des symboles et non des chaînes.
Phrogz
1
@Phrogz: Oui, mais vous êtes autorisé à utiliser des expressions régulières dessus. Vous n'invoquez même pas Cthulhu! :) Bien que vous obteniez à la [:method1]place.
Andrew Grimm
113
TestClass.methods(false) 

pour obtenir uniquement les méthodes appartenant à cette classe uniquement.

TestClass.instance_methods(false) renvoie les méthodes de votre exemple donné (car ce sont des méthodes d'instance de TestClass).

Bijan
la source
2
C'est un excellent moyen de tester si une classe a des méthodes polymorphes à partir d'une pseudo-interface / classe de base abstraite sans avoir à essayer d'appeler les méthodes directement.
Daniel Doezema
2
La réponse acceptée est excellente, mais celle-ci est probablement la raison pour laquelle plus de gens viendront ici!
Aaron
Cela devrait certainement être la réponse acceptée. MERCI!
Vinicius Brasil
38
TestClass.instance_methods

ou sans toutes les méthodes héritées

TestClass.instance_methods - Object.methods

(Était 'TestClass.methods - Object.methods')

Pavage
la source
25
ou sans méthodes héritées: TestClass.methods(false).
sawa
2
@sawa TestClass.methods(false)retourne vide
Vladimir Tsukanov
1
Cette réponse est fausse; les résultats ne comprendront method1, method2ou method3, comme ce sont des méthodes d' instances de la classe, et non pas des méthodes de l' TestClassobjet lui - même.
Phrogz
1
@Phrogz: Oups ... oui, 'TestClass.instance_methods - Object.methods', ou 'TestClass.new.methods - Object.methods' ... cela m'apprendra à ne pas allumer une console. Est-il préférable pour moi de supprimer cette réponse ou de la modifier?
Pavling
1
@Pavling Modifiez votre réponse pour qu'elle soit correcte. (Rapidement, avant que l'OP n'attribue le crédit à quelqu'un d'autre! :)
Phrogz
6

Vous pouvez obtenir une liste plus détaillée (par exemple structurée en définissant une classe) avec des gemmes comme le débogage ou looksee .

J -_- L
la source
6
$ irb --simple-prompt

class TestClass
  def method1
  end

  def method2
  end

  def method3
  end
end

tc_list = TestClass.instance_methods(false)
#[:method1, :method2, :method3]
puts tc_list
#method1
#method2
#method3
Douglas G. Allen
la source
2
Ceci est trop similaire aux autres réponses et n'ajoute aucune information supplémentaire ni clarté.
Substantiel le
3
Vous avez omis de mentionner qu'il est également très tard. : D
Douglas
2

Selon Ruby Doc instance_methods

Renvoie un tableau contenant les noms des méthodes d'instance publique et protégée dans le récepteur. Pour un module, ce sont les méthodes publiques et protégées; pour une classe, ce sont les méthodes d'instance (et non singleton). Si le paramètre facultatif est false, les méthodes de tous les ancêtres ne sont pas incluses. Je prends l'exemple de la documentation officielle.

module A
  def method1()  
    puts "method1 say hi"
  end
end
class B
  include A #mixin
  def method2()  
     puts "method2 say hi"
  end
end
class C < B #inheritance
  def method3() 
     puts "method3 say hi"
  end
end

Voyons la sortie.

A.instance_methods(false)
  => [:method1]

A.instance_methods
  => [:method1]
B.instance_methods
 => [:method2, :method1, :nil?, :===, ...# ] # methods inherited from parent class, most important :method1 is also visible because we mix module A in class B

B.instance_methods(false)
  => [:method2]
C.instance_methods
  => [:method3, :method2, :method1, :nil?, :===, ...#] # same as above
C.instance_methods(false)
 => [:method3]
Mukesh Kumar Gupta
la source
1

Pour obtenir uniquement ses propres méthodes et exclure celles héritées:

Depuis l'instance:

self.methods - self.class.superclass.instance_methods

De dehors:

TestClass.instance_methods - TestClass.superclass.instance_methods

Ajoutez-le à la classe:

class TestClass
  class << self
    def own_methods
      self.instance_methods - self.superclass.instance_methods
    end
  end
end

TestClass.own_methods
=> [:method1, :method2, method3]

(avec ruby ​​2.6.x)

nakwa
la source