0

I heard that Ruby has strong reflection and metaprogramming ability. I am wondering if there is a way to show all the methods a class or an object which I can call?

the Tin Man
  • 158,662
  • 42
  • 215
  • 303
biluochun2010
  • 109
  • 1
  • 7

3 Answers3

2

Almost!

You can call .methods on any object (including a class) to get a list of which methods are available on that object.

However, #method_missing allows Ruby objects to respond to messages which aren't actually defined on that object. It's possible to find out for a particular method name whether an object responds to that message, but it's not possible to list all of the methods which can be caught this way.

Gareth
  • 133,157
  • 36
  • 148
  • 157
1

If you are looking for all the public and protected methods the instances of your class have, then you may call instance_methods on the class itself.

It also accepts a boolean optional argument set as true as default. True will list all the instance methods of your class superclasses, if false it will return only your class ones.


the Tin Man
  • 158,662
  • 42
  • 215
  • 303
Barbared
  • 800
  • 1
  • 8
  • 25
0

An example is often helpful. Here I've defined two classes, A and B, where B is a subclass of A. A has one public class method, one public instance method and one private instance method.

Class B has two public class methods, five public instance methods and two private instance methods. Three of the public instance methods (..owners) are for displaying the owners of various methods. In addition, B has all of A's methods. The focus will be on B.

I've begun the names of all methods with three underscores, simply to facilitate their extraction from lists of methods Ruby returns. For example, B has 52 (class) methods, but the only ones whose names begin begin with three underscores are defined in A and B .

I think you can learn a lot by studying the following. Not only should it answer your question, but it will acquaint you will several Ruby methods that are quite handy, namely:

.

class A
  def ___aim_pub; end
  def self.___acm_pub; end
  private
  def ___aim_pvt; end
end

class B < A
  def self.___my_owners
    (my methods).each { |m| puts "#{m} owner = #{method(m).owner}" }
  end
  def ___my_owners
    (my methods).each { |m| puts "#{m} owner = #{method(m).owner}" }
  end
  def ___my_private_owners
    (my self.class.private_instance_methods).each { |m|
      puts "#{m} owner = #{method(m).owner}" }
  end

  def ___b1im_pub; end
  def ___b2im_pub; end
  def self.___b1cm_pub; end
  def self.___b2cm_pub; end

  private
  def ___b1im_pvt; end
  def ___b2im_pvt; end
end

Helper

def my(ms)
  ms.select { |m| m.to_s[0,3] == '___' }
end

Public class methods

B.methods.size
  #=> 103
my B.methods
  #=> [:___my_owners, :___b1cm_pub, :___b2cm_pub, :___acm_pub]
B.methods false
  #=> [:___my_owners, :___b1cm_pub, :___b2cm_pub]
B.___my_owners
  # ___my_owners owner = #<Class:B>
  # ___b1cm_pub owner  = #<Class:B>
  # ___b2cm_pub owner  = #<Class:B>
  # ___acm_pub owner   = #<Class:A>

b = B.new
  #=> #<B:0x000001028bbdb8>

Public instance methods

B.instance_methods.size
  #=> 60
B.instance_methods == b.methods
  #=> true
my B.instance_methods
  #=> [:___my_owners, :___my_private_owners, :___b1im_pub,
  #    :___b2im_pub, :___aim_pub]
B.instance_methods false
  #=> [:___my_owners, :___my_private_owners, :___b1im_pub, :___b2im_pub]
b.___my_owners
  # ___my_owners owner = B
  # ___my_private_owners owner = B
  # ___b1im_pub owner = B
  # ___b2im_pub owner = B
  # ___aim_pub owner  = A

Private instance methods

B.private_instance_methods.size
  #=> 78
my B.private_instance_methods
  #=> [:___b1im_pvt, :___b2im_pvt, :___aim_pvt]
B.private_instance_methods false
  #=> [:___b1im_pvt, :___b2im_pvt]
b.___my_private_owners
  # ___b1im_pvt owner = B
  # ___b2im_pvt owner = B
  # ___aim_pvt owner  = A
Cary Swoveland
  • 106,649
  • 6
  • 63
  • 100