Pobierz listę metod instancji klasy

98

Mam klasę:

class TestClass
  def method1
  end

  def method2
  end

  def method3
  end
end

Jak mogę uzyskać listę moich metod w tej klasie ( method1, method2, method3)?

Vladimir Tsukanov
źródło

Odpowiedzi:

115

Właściwie chcesz TestClass.instance_methods, chyba że jesteś zainteresowany tym TestClass, co samo może zrobić.

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

Lub możesz zadzwonić methods(nie instance_methods) na obiekt:

test_object = TestClass.new
test_object.methods.grep(/method1/) # => ["method1"]
Andrew Grimm
źródło
3
Heh, pokonałeś mnie o 47 sekund. +1
Phrogz
2
Kiedy próbuję print TestClass.new.instance_methods, pojawia się ten błądmy_class.rb:10:in <main>: undefined method instance_methods for #<TestClass:0x96b9d20> (NoMethodError)
Vladimir Tsukanov
Musisz tylko zrobić TestClass.new.methods. Może „to” było w mojej odpowiedzi niejednoznaczne.
Andrew Grimm,
Zauważ, że w Rubim 1.9+ tablica nazw metod to symbole, a nie łańcuchy.
Phrogz
1
@Phrogz: Tak, ale możesz używać na nich wyrażeń regularnych. Nawet nie przywołujesz Cthulhu! :) Chociaż [:method1]zamiast tego dostałbyś.
Andrew Grimm,
113
TestClass.methods(false) 

aby uzyskać tylko metody należące tylko do tej klasy.

TestClass.instance_methods(false) zwróci metody z podanego przykładu (ponieważ są one metodami instancji TestClass).

Bijan
źródło
2
Jest to świetny sposób na sprawdzenie, czy klasa ma poddane polimorfizacji metody z pseudointerfejsu / abstrakcyjnej klasy bazowej, bez konieczności bezpośredniego wywoływania tych metod.
Daniel Doezema
2
Zaakceptowana odpowiedź jest świetna, ale prawdopodobnie po to przyjdzie więcej ludzi!
Aaron,
To zdecydowanie powinna być akceptowana odpowiedź. DZIĘKI!
Vinicius Brasil
38
TestClass.instance_methods

lub bez wszystkich odziedziczonych metod

TestClass.instance_methods - Object.methods

(Było „TestClass.methods - Object.methods”)

Pavling
źródło
25
lub bez dziedziczone metody: TestClass.methods(false).
sawa
2
@sawa TestClass.methods(false)powraca pusty
Vladimir Tsukanov
1
Ta odpowiedź jest błędna; wyniki nie będą zawierać method1, method2lub method3, ponieważ są to metody wystąpień klasy, a nie metody TestClasssamego obiektu.
Phrogz
1
@Phrogz: Ups ... tak, 'TestClass.instance_methods - Object.methods' lub 'TestClass.new.methods - Object.methods' ... to nauczy mnie, jak nie odpalać konsoli. Czy najlepiej jest dla mnie usunąć tę odpowiedź, czy ją edytować?
Pavling
1
@Pavling Zdecydowanie edytuj swoją odpowiedź, aby była poprawna. (Szybko, zanim PO przydzieli kredyt komuś innemu! :)
Phrogz
6

Możesz uzyskać bardziej szczegółową listę (np . Uporządkowaną przez zdefiniowanie klasy) z klejnotami, takimi jak debugowanie lub looksee .

J L
źródło
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
źródło
2
Jest to zbyt podobne do innych odpowiedzi i nie dodaje żadnych dodatkowych informacji ani jasności.
Znaczący
3
Nie wspomniałeś, że jest też bardzo późno. : D
Douglas G. Allen
2

Według Ruby Doc instance_methods

Zwraca tablicę zawierającą nazwy publicznych i chronionych metod wystąpienia w odbiorniku. W przypadku modułu są to metody publiczne i chronione; dla klasy są to metody instancji (nie pojedyncze). Jeśli opcjonalny parametr ma wartość false, metody wszystkich przodków nie są uwzględniane. Biorę przykład oficjalnej dokumentacji.

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

Zobaczmy wynik.

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
źródło
1

Aby uzyskać tylko własne metody i wykluczyć odziedziczone:

Z poziomu instancji:

self.methods - self.class.superclass.instance_methods

Z zewnątrz:

TestClass.instance_methods - TestClass.superclass.instance_methods

Dodaj to do zajęć:

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

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

(z rubinem 2.6.x)

nakwa
źródło