Obter uma lista dos métodos de instância de uma classe

98

Eu tenho uma aula:

class TestClass
  def method1
  end

  def method2
  end

  def method3
  end
end

Como posso obter uma lista dos meus métodos dessa classe ( method1, method2, method3)?

Vladimir Tsukanov
fonte

Respostas:

114

Você realmente quer TestClass.instance_methods, a menos que esteja interessado no que TestClassela mesma pode fazer.

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 você pode chamar methods(não instance_methods) no objeto:

test_object = TestClass.new
test_object.methods.grep(/method1/) # => ["method1"]
Andrew Grimm
fonte
3
Heh, você chegou antes de mim por 47 segundos. +1
Phrogz
2
Quando tento print TestClass.new.instance_methods, recebo este erromy_class.rb:10:in <main>: undefined method instance_methods for #<TestClass:0x96b9d20> (NoMethodError)
Vladimir Tsukanov
Você só precisa fazer TestClass.new.methods. Talvez "isso" tenha sido ambíguo em minha resposta.
Andrew Grimm
Observe que no Ruby 1.9+ o array de nomes de métodos são símbolos, não strings.
Phrogz
1
@Phrogz: Sim, mas você pode usar expressões regulares neles. Você nem mesmo convoca Cthulhu! :) Embora você receba [:method1]em seu lugar.
Andrew Grimm
113
TestClass.methods(false) 

para obter apenas métodos que pertencem apenas a essa classe.

TestClass.instance_methods(false) retornaria os métodos do seu exemplo dado (uma vez que são métodos de instância de TestClass).

Bijan
fonte
2
Essa é uma ótima maneira de testar se uma classe tem métodos polimorfos de uma classe base pseudo-Interface / Abstract sem ter que tentar chamar os métodos diretamente.
Daniel Doezema
2
A resposta aceita é ótima, mas é provável que mais pessoas venham aqui!
Aaron de
Esta definitivamente deveria ser a resposta aceita. OBRIGADO!
Vinicius Brasil
38
TestClass.instance_methods

ou sem todos os métodos herdados

TestClass.instance_methods - Object.methods

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

Pavling
fonte
25
ou sem métodos herdados: TestClass.methods(false).
sawa
2
@sawa TestClass.methods(false)retorna vazio
Vladimir Tsukanov
1
Essa resposta está errada; os resultados não incluirão method1, method2ou method3, como esses são métodos de instâncias da classe, não métodos do TestClasspróprio objeto.
Phrogz
1
@Phrogz: Oops ... sim, 'TestClass.instance_methods - Object.methods' ou 'TestClass.new.methods - Object.methods' ... isso vai me ensinar a não iniciar um console. É melhor excluir esta resposta ou editá-la?
Pavling
1
@Pavling Definitivamente edite sua resposta para ficar correta. (Rapidamente, antes que o OP atribua o crédito a outra pessoa! :)
Phrogz
6

Você pode obter uma lista mais detalhada (por exemplo, estruturada pela definição de classe) com joias como depuração ou looksee .

J -_- L
fonte
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
fonte
2
Isso é muito semelhante a outras respostas e não adiciona nenhuma informação adicional ou clareza.
Substancial de
3
Você não mencionou que também é muito tarde. : D
Douglas G. Allen
2

De acordo com Ruby Doc instance_methods

Retorna uma matriz contendo os nomes dos métodos de instância públicos e protegidos no receptor. Para um módulo, esses são os métodos públicos e protegidos; para uma classe, eles são os métodos de instância (não singleton). Se o parâmetro opcional for falso, os métodos de quaisquer ancestrais não serão incluídos. Estou usando o exemplo de documentação oficial.

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

Vamos ver o resultado.

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

Para obter apenas métodos próprios e excluir os herdados:

De dentro da instância:

self.methods - self.class.superclass.instance_methods

De fora:

TestClass.instance_methods - TestClass.superclass.instance_methods

Adicione-o à classe:

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

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

(com ruby ​​2.6.x)

Nakwa
fonte