Liste der Instanzmethoden einer Klasse abrufen

98

Ich habe ein klasse:

class TestClass
  def method1
  end

  def method2
  end

  def method3
  end
end

Wie kann ich eine Liste meiner Methoden in dieser Klasse erhalten ( method1, method2, method3)?

Vladimir Tsukanov
quelle

Antworten:

114

Sie wollen tatsächlich TestClass.instance_methods, es sei denn, Sie interessieren sich für das, was TestClassselbst tun kann.

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"]

Oder Sie können das Objekt aufrufen methods(nicht instance_methods):

test_object = TestClass.new
test_object.methods.grep(/method1/) # => ["method1"]
Andrew Grimm
quelle
3
Heh, du hast mich um 47 Sekunden geschlagen. +1
Phrogz
2
Wenn ich es versuche print TestClass.new.instance_methods, bekomme ich diesen Fehlermy_class.rb:10:in <main>: undefined method instance_methods for #<TestClass:0x96b9d20> (NoMethodError)
Vladimir Tsukanov
Sie müssen nur tun TestClass.new.methods. Vielleicht war "es" in meiner Antwort mehrdeutig.
Andrew Grimm
Beachten Sie, dass unter Ruby 1.9+ das Array der Methodennamen Symbole und keine Zeichenfolgen sind.
Phrogz
1
@Phrogz: Ja, aber Sie dürfen reguläre Ausdrücke verwenden. Du beschwörst nicht einmal Cthulhu! :) Obwohl du [:method1]stattdessen bekommen würdest .
Andrew Grimm
113
TestClass.methods(false) 

um nur Methoden zu erhalten, die nur zu dieser Klasse gehören.

TestClass.instance_methods(false) würde die Methoden aus Ihrem angegebenen Beispiel zurückgeben (da es sich um Instanzmethoden von TestClass handelt).

Bijan
quelle
2
Dies ist eine großartige Möglichkeit, um zu testen, ob eine Klasse polymorphe Methoden aus einer Pseudo-Interface / Abstract-Basisklasse hat, ohne die Methoden direkt aufrufen zu müssen.
Daniel Doezema
2
Akzeptierte Antwort ist großartig, aber diese ist wahrscheinlich, wofür mehr Leute hierher kommen werden!
Aaron
Dies sollte definitiv die akzeptierte Antwort sein. VIELEN DANK!
Vinicius Brasil
38
TestClass.instance_methods

oder ohne alle geerbten Methoden

TestClass.instance_methods - Object.methods

(War 'TestClass.methods - Object.methods')

Pflasterung
quelle
25
oder ohne geerbte Methoden : TestClass.methods(false).
Sawa
2
@sawa TestClass.methods(false)kehrt leer zurück
Vladimir Tsukanov
1
Diese Antwort ist falsch; die Ergebnisse nicht enthalten method1, method2oder method3, wie die Methoden der sind Instanzen der Klasse, nicht Methoden des TestClassObjekts selbst.
Phrogz
1
@Phrogz: Ups ... ja, 'TestClass.instance_methods - Object.methods' oder 'TestClass.new.methods - Object.methods' ... das bringt mir bei, dass ich keine Konsole hochgefahren habe. Ist es für mich am besten, diese Antwort zu löschen oder zu bearbeiten?
Pavling
1
@Pavling Bearbeiten Sie Ihre Antwort auf jeden Fall so, dass sie korrekt ist. (Schnell, bevor das OP das Guthaben jemand anderem zuweist! :)
Phrogz
6

Sie können eine detailliertere Liste (z. B. strukturiert durch Definieren der Klasse) mit Edelsteinen wie Debugging oder Looksee erhalten .

J L
quelle
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
quelle
2
Dies ist anderen Antworten zu ähnlich und fügt keine zusätzlichen Informationen oder Klarheit hinzu.
Wesentlich
3
Sie haben falsch erwähnt, dass es auch sehr spät ist. : D
Douglas G. Allen
2

Laut Ruby Doc instance_methods

Gibt ein Array zurück, das die Namen der öffentlichen und geschützten Instanzmethoden im Empfänger enthält. Für ein Modul sind dies die öffentlichen und geschützten Methoden. Für eine Klasse sind dies die Instanzmethoden (nicht Singleton-Methoden). Wenn der optionale Parameter false ist, sind die Methoden aller Vorfahren nicht enthalten. Ich nehme das offizielle Dokumentationsbeispiel.

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

Lassen Sie uns die Ausgabe sehen.

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
quelle
0

So erhalten Sie nur eigene Methoden und schließen geerbte aus:

Aus der Instanz heraus:

self.methods - self.class.superclass.instance_methods

Von außen:

TestClass.instance_methods - TestClass.superclass.instance_methods

Fügen Sie es der Klasse hinzu:

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

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

(mit Rubin 2.6.x)

Nakwa
quelle