Получить список методов экземпляра класса

98

У меня есть класс:

class TestClass
  def method1
  end

  def method2
  end

  def method3
  end
end

Как я могу получить список моих методов в этом классе ( method1, method2, method3)?

Владимир Цуканов
источник

Ответы:

115

Вы действительно хотите TestClass.instance_methods, если вас не интересует, на что TestClassон способен.

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

Или вы можете позвонить methods(не instance_methods) на объект:

test_object = TestClass.new
test_object.methods.grep(/method1/) # => ["method1"]
Эндрю Гримм
источник
3
Хех, ты опередил меня на 47 секунд. +1
Phrogz
2
Когда я пытаюсь print TestClass.new.instance_methods, я получаю эту ошибкуmy_class.rb:10:in <main>: undefined method instance_methods for #<TestClass:0x96b9d20> (NoMethodError)
Владимир Цуканов
Вам только нужно сделать TestClass.new.methods. Возможно, «это» было двусмысленным в моем ответе.
Эндрю Гримм
Обратите внимание, что в Ruby 1.9+ массив имен методов представляет собой символы, а не строки.
Phrogz
1
@Phrogz: Да, но вы можете использовать для них регулярные выражения. Вы даже не призываете Ктулху! :) Хотя бы [:method1]взамен получил.
Эндрю Гримм
113
TestClass.methods(false) 

чтобы получить только методы, принадлежащие только этому классу.

TestClass.instance_methods(false) вернет методы из вашего данного примера (поскольку они являются методами экземпляра TestClass).

Биджан
источник
2
Это отличный способ проверить, имеет ли класс полиморфизированные методы из псевдоинтерфейсного / абстрактного базового класса, без необходимости напрямую вызывать методы.
Daniel Doezema
2
Принятый ответ - это здорово, но, вероятно, именно за этим сюда придут еще люди!
Аарон
Это определенно должен быть принятый ответ. СПАСИБО!
Vinicius Brasil
38
TestClass.instance_methods

или без всех унаследованных методов

TestClass.instance_methods - Object.methods

(Было 'TestClass.methods - Object.methods')

Павлинг
источник
25
или без унаследованных методов: TestClass.methods(false).
sawa
2
@sawa TestClass.methods(false)возвращается пустым
Владимир Цуканов
1
Этот ответ неверен; результаты не будут включать method1, method2или method3, поскольку это методы экземпляров класса, а не методы самого TestClassобъекта.
Phrogz
1
@Phrogz: Ой ... да, TestClass.instance_methods - Object.methods или TestClass.new.methods - Object.methods ... это научит меня не запускать консоль. Мне лучше удалить этот ответ или отредактировать его?
Pavling
1
@Pavling Обязательно отредактируйте свой ответ, чтобы он был правильным. (Быстро, прежде чем ОП присвоит кредит кому-то другому! :)
Phrogz
6

Вы можете получить более подробный список (например, структурированный путем определения класса) с такими жемчужинами, как отладка или просмотр .

J -_- L
источник
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
Это слишком похоже на другие ответы и не добавляет никакой дополнительной информации или ясности.
Существенный
3
Вы не преминули упомянуть, что это тоже очень поздно. : D
Дуглас Г. Аллен
2

Согласно Ruby Doc instance_methods

Возвращает массив, содержащий имена методов общедоступного и защищенного экземпляра в получателе. Для модуля это общедоступные и защищенные методы; для класса это методы экземпляра (а не одиночные). Если необязательный параметр имеет значение false, методы каких-либо предков не включаются. Я беру пример официальной документации.

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

Посмотрим на результат.

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]
Мукеш Кумар Гупта
источник
1

Чтобы получить только собственные методы и исключить унаследованные:

Изнутри экземпляра:

self.methods - self.class.superclass.instance_methods

Снаружи:

TestClass.instance_methods - TestClass.superclass.instance_methods

Добавьте его в класс:

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

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

(с Ruby 2.6.x)

наква
источник