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)?

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

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).


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')


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
$ 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

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]

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)

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.