Obtener una lista de los métodos de instancia de una clase

98

Tengo una clase:

class TestClass
  def method1
  end

  def method2
  end

  def method3
  end
end

¿Cómo puedo obtener una lista de mis métodos de esta clase ( method1, method2, method3)?

Vladimir Tsukanov
fuente

Respuestas:

115

Realmente lo desea TestClass.instance_methods, a menos que esté interesado en lo que TestClasspuede hacer por sí mismo.

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

O puede llamar methods(no instance_methods) al objeto:

test_object = TestClass.new
test_object.methods.grep(/method1/) # => ["method1"]
Andrew Grimm
fuente
3
Je, me ganaste 47 segundos. +1
Phrogz
2
Cuando lo intento print TestClass.new.instance_methods, aparece este errormy_class.rb:10:in <main>: undefined method instance_methods for #<TestClass:0x96b9d20> (NoMethodError)
Vladimir Tsukanov
Solo necesitas hacer TestClass.new.methods. Tal vez "eso" fue ambiguo en mi respuesta.
Andrew Grimm
Tenga en cuenta que en Ruby 1.9+, la matriz de nombres de métodos son símbolos, no cadenas.
Phrogz
1
@Phrogz: Sí, pero puedes usar expresiones regulares en ellos. ¡Ni siquiera convocas a Cthulhu! :) Aunque en su [:method1]lugar obtendrías .
Andrew Grimm
113
TestClass.methods(false) 

para obtener solo métodos que pertenecen solo a esa clase.

TestClass.instance_methods(false) devolvería los métodos de su ejemplo dado (ya que son métodos de instancia de TestClass).

Bijan
fuente
2
Esta es una excelente manera de probar si una clase tiene métodos polimorfizados de una clase base pseudo-Interfaz / abstracta sin tener que intentar llamar a los métodos directamente.
Daniel Doezema
2
La respuesta aceptada es excelente, ¡pero esta es probablemente la razón por la que vendrán más personas aquí!
Aaron
Esta definitivamente debería ser la respuesta aceptada. ¡GRACIAS!
Vinicius Brasil
38
TestClass.instance_methods

o sin todos los métodos heredados

TestClass.instance_methods - Object.methods

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

Pavling
fuente
25
o sin métodos heredados: TestClass.methods(false).
sawa
2
@sawa TestClass.methods(false)vuelve vacío
Vladimir Tsukanov
1
Esta respuesta es incorrecta; los resultados no incluirán method1, method2o method3, ya que son métodos de instancias de la clase, no métodos del TestClassobjeto en sí.
Phrogz
1
@Phrogz: Vaya ... sí, 'TestClass.instance_methods - Object.methods', o 'TestClass.new.methods - Object.methods' ... eso me enseñará a no encender una consola. ¿Es mejor para mí eliminar esta respuesta o editarla?
Pavling
1
@Pavling Definitivamente edite su respuesta para que sea correcta. (¡Rápido, antes de que el OP asigne el crédito a otra persona! :)
Phrogz
6

Puede obtener una lista más detallada (por ejemplo, estructurada mediante la definición de clase) con gemas como depuración o looksee .

J -_- L
fuente
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
fuente
2
Esto es demasiado similar a otras respuestas y no agrega información adicional ni claridad.
Sustancial
3
Faltó mencionar que también es muy tarde. : D
Douglas G. Allen
2

Según Ruby Doc instance_methods

Devuelve una matriz que contiene los nombres de los métodos de instancia pública y protegida en el receptor. Para un módulo, estos son los métodos públicos y protegidos; para una clase, son los métodos de instancia (no singleton). Si el parámetro opcional es falso, no se incluyen los métodos de ningún antepasado. Estoy tomando el ejemplo de la documentación 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

Veamos el 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
fuente
0

Para obtener solo métodos propios y excluir los heredados:

Desde dentro de la instancia:

self.methods - self.class.superclass.instance_methods

Desde afuera:

TestClass.instance_methods - TestClass.superclass.instance_methods

Agréguelo a la clase:

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

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

(con rubí 2.6.x)

nakwa
fuente