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

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

class TestClass
  def method1
  end

  def method2
  end

  def method3
  end
end

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


person Vladimir Tsukanov    schedule 24.06.2011    source источник


Ответы (6)


На самом деле вам нужен 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"]
person Andrew Grimm    schedule 24.06.2011
comment
Хех, ты опередил меня на 47 секунд. +1 - person Phrogz; 24.06.2011
comment
Когда я пытаюсь print TestClass.new.instance_methods, я получаю эту ошибку my_class.rb:10:in <main>: undefined method instance_methods for #<TestClass:0x96b9d20> (NoMethodError) - person Vladimir Tsukanov; 24.06.2011
comment
Вам нужно только сделать TestClass.new.methods. Возможно, это было двусмысленно в моем ответе. - person Andrew Grimm; 24.06.2011
comment
Обратите внимание, что в Ruby 1.9+ массив имен методов является символами, а не строками. - person Phrogz; 24.06.2011
comment
@Phrogz: Да, но вам разрешено использовать для них регулярные выражения. Ты даже не призываешь Ктулху! :) Хотя вместо этого вы получите [:method1]. - person Andrew Grimm; 24.06.2011

TestClass.methods(false) 

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

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

person Bijan    schedule 09.03.2013
comment
Это отличный способ проверить, имеет ли класс полиморфные методы из базового класса псевдоинтерфейса/абстрактного, без необходимости пытаться вызывать методы напрямую. - person Daniel Doezema; 19.04.2013
comment
Принятый ответ отличный, но, скорее всего, именно за этим сюда придет больше людей! - person Aaron; 12.04.2016
comment
Это определенно должен быть принятый ответ. БЛАГОДАРНОСТЬ! - person vinibrsl; 07.01.2019
comment
@Aaron: Я очень сомневаюсь в этом, поскольку этот ответ неправильный. Object#methods возвращает методы, которые вы можете вызвать для объекта. Какие методы можно вызывать для объекта? Те, что определены в его классе. Это означает, что TestClass.methods возвращает список методов, которые вы можете вызвать для TestClass, то есть методов, определенных в его классе. Какой у TestClass класс? Это Class. Итак, TestClass.methods дает вам методы, определенные в Class, а не те, которые определены в TestClass. Не уверен, как этот ответ получил 116 голосов, когда кто-то даже - person Jörg W Mittag; 23.09.2020
comment
…самое отдаленное мимолетное знание мгновенно признало бы его неверным. Или, вы знаете, просто скопируйте и вставьте этот код и запустите его, и вы увидите, что он неверен. - person Jörg W Mittag; 23.09.2020
comment
@ViniciusBrasil: этот ответ неверен, поэтому он определенно не должен быть принятым ответом, и тот факт, что у него 116 голосов, серьезно огорчает, учитывая, что просто скопировать и вставить код и попробовать занимает 1 секунду. это, и меньше одной секунды, чтобы просто все обдумать. - person Jörg W Mittag; 23.09.2020
comment
Я не могу вспомнить, что происходило 4 с лишним года назад, поэтому я предложу свое лучшее предположение. Принятый в настоящее время ответ является подробным и дает отличное понимание различий между Object#methods и Object#instance_methods. Я предполагаю, что я обнаружил, что использование аргумента false в этом ответе было тем, что меня интересовало, поскольку TestClass.instance_methods.size равно 64 на Ruby 2.7.1, но TestClass.instance_methods(false).size ограничено тремя определенными. Я, наверное, поленился и не хотел цеплять grep ????‍♂️ - person Aaron; 24.09.2020

TestClass.instance_methods

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

TestClass.instance_methods - Object.methods

(Было «TestClass.methods — Object.methods»)

person Pavling    schedule 24.06.2011
comment
или без унаследованных методов: TestClass.methods(false). - person sawa; 24.06.2011
comment
@sawa TestClass.methods(false) возвращает пустое значение - person Vladimir Tsukanov; 24.06.2011
comment
Этот ответ неверен; результаты не будут включать method1, method2 или method3, так как это методы экземпляров класса, а не методы самого объекта TestClass. - person Phrogz; 24.06.2011
comment
@Phrogz: Упс... да, "TestClass.instance_methods - Object.methods" или "TestClass.new.methods - Object.methods"... это научит меня не запускать консоль. Мне лучше удалить этот ответ или отредактировать его? - person Pavling; 24.06.2011
comment
@Phrogz - этот ответ работает для меня, я получаю [:method1, :method2, :method3] с print TestClass.new.methods - Object.methods - person Vladimir Tsukanov; 24.06.2011
comment
@Vladimir @Phrogz Вопрос был противоречивым. В заголовке (до редактирования Тео) запрашивались методы класса, а в теле — method1 и т. д. - person sawa; 24.06.2011
comment
@Pavling Определенно отредактируйте свой ответ, чтобы он был правильным. (Быстро, прежде чем ОП присвоит кредит кому-то другому! :) - person Phrogz; 24.06.2011
comment
@Phrogz: сохранение (исправленного) ответа также является хорошим способом показать потенциальную ошибку. - person Andrew Grimm; 24.06.2011

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

person J-_-L    schedule 24.06.2011

Согласно 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]
person Mukesh Kumar Gupta    schedule 06.06.2017

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

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

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]

(с рубином 2.6.x)

person nakwa    schedule 23.04.2020