Listing an Objects Methods

Listing an Object s Methods

Problem

Given an unfamiliar object, you want to see what methods are available to call.

Solution

All Ruby objects implement the Object#methods method. It returns an array containing the names of the object's public instance methods:

Object.methods # => ["name", "private_class_method", "object_id", "new", # "singleton_methods", "method_defined?", "equal?", … ]

To get a list of the singleton methods of some object (usually, but not always, a class), use Object#singleton_methods:

Object.singleton_methods # => [] Fixnum.singleton_methods # => ["induced_from"] class MyClass def MyClass.my_singleton_method end def my_instance_method end end MyClass.singleton_methods # => ["my_singleton_method"]

To list the instance methods of a class, call instance_methods on the object. This lets you list the instance methods of a class without instantiating the class:

''.methods == String.instance_methods # => true

The output of these methods are most useful when sorted:

Object.methods.sort # => ["<", "<=", "<=>", "==", "===", "=~", ">", ">=", # "__id__", "__send__", "allocate", "ancestors", … ]

Ruby also defines some elementary predicates along the same lines. To see whether a class defines a certain instance method, call method_defined? on the class or respond_to? on an instance of the class. To see whether a class defines a certain class method, call respond_to? on the class:

MyClass.method_defined? :my_instance_method # => true MyClass.new.respond_to? :my_instance_method # => true MyClass.respond_to? :my_instance_method # => false MyClass.respond_to? :my_singleton_method # => true

 

Discussion

It often happens that while you're in an interactive Ruby session, you need to look up which methods an object supports, or what a particular method is called. Looking directly at the object is faster than looking its class up in a book. If you're using a library like Rails or Facets, or your code has been adding methods to the built-in classes, it's also more reliable.

Noninteractive code can also benefit from knowing whether a given object implements a certain method. You can use this to enforce an interface, allowing any object to be passed into a method so long as the argument implements certain methods (see Recipe 10.16).

If you find yourself using respond_to? a lot in an interactive Ruby session, you're a good customer for irb's autocomplete feature. Put the following line in your .irbrc file or equivalent:

require 'irb/completion' #Depending on your system, you may also have to add the following line: IRB.conf[:use_readline] = true

Then you can type (for instance) "[1,2,3].", hit the Tab key, and see a list of all the methods you can call on the array [1, 2, 3].

methods, instance_methods, and singleton_methods will only return public methods, and method_defined? will only return true if you give it the name of a public method. Ruby provides analagous methods for discovering protected and private methods, though these are less useful. All the relevant methods are presented in Table 10-1.

Table 10-1. Discovering protected and private methods

Goal

Public

Protected

Private

List the methods of an object

methods or public_methods

protected_methods

private_methods

List the instance methods defined by a class

instance_methods or public_instance_methods

protected_instance_methods

private_instance_methods

List the singleton methods defined by a class

singleton_methods

N/A

N/A

Does this class define such-and-such an instance method?

method_defined? or public_method_defined?

protected_method_defined?

private_method_defined?

Will this object respond to such-and-such an instance method?

respond_to?

N/A

N/A

Just because you can see the names of protected or private methods in a list doesn't mean you can call the methods, or that respond_to? will find them:

String.private_instance_methods.sort # => ["Array", "Float", "Integer", "String", "'", "abort", "at_exit", # "autoload","autoload?", "binding", "block_given?", "callcc", … ] String.new.respond_to? :autoload? # => false String.new.autoload? # NoMethodError: private method 'autoload?' called for "":String

 

See Also

Категории