Module
, Class
, and Object
implement several callback methods, or hooks. These methods are
not defined by default, but if you define them for a module, class, or
object, then they will be invoked when certain events occur. This gives
you an opportunity to extend Ruby’s behavior when classes are
subclassed, when modules are included, or when methods are defined. Hook
methods (except for some deprecated ones not described here) have names that end in
“ed.”
When a new class is defined, Ruby invokes the class
method inherited
on the
superclass of the new class, passing the new class object as the
argument. This allows classes to add behavior to or enforce constraints
on their descendants. Recall that class methods are inherited, so that
the an inherited
method will be
invoked if it is defined by any of the ancestors of the new class.
Define Object.inherited
to receive
notification of all new classes that are defined:
def Object.inherited(c) puts "class #{c} < #{self}" end
When a module is included into a class or into another module, the
included
class method of the included
module is invoked with the class or module object into which it was
included as an argument. This gives the included module an opportunity
to augment or alter the class in whatever way it wants—it effectively
allows a module to define its own meaning for include
. In addition to adding methods to the
class into which it is included, a module with an included
method might also alter the existing
methods of that class, for example:
module Final # A class that includes Final can't be subclassed def self.included(c) # When included in class c c.instance_eval do # Define a class method of c def inherited(sub) # To detect subclasses raise Exception, # And abort with an exception "Attempt to create subclass #{sub} of Final class #{self}" end end end end
Similarly, if a module defines a class method named extended
, that method will be invoked any time
the module is used to extend an object (with Object.extend
). The argument to the extended
method will be the object that was
extended, of course, and the extended
method can take whatever actions it wants on that object.
In addition to hooks for tracking classes and the modules they
include, there are also hooks for tracking the methods of classes and
modules and the singleton methods of arbitrary objects. Define a class
method named method_added
for any
class or module and it will be invoked when an instance method is
defined for that class or module:
def String.method_added(name) puts "New instance method #{name} added to String" end
Note that the method_added
class method is inherited by subclasses of the class on which it is
defined. But no class argument is passed to the hook, so there is no way
to tell whether the named method was added to the class that defines
method_added
or whether it was added
to a subclass of that class. A workaround for this problem is to define
an inherited
hook on any class that
defines a method_added
hook. The
inherited
method can then define a
method_added
method for each
subclass.
When a singleton method is defined for any object, the method
singleton_method_added
is invoked on that
object, passing the name of the new method. Remember that for classes, singleton
methods are class methods:
def String.singleton_method_added(name) puts "New class method #{name} added to String" end
Interestingly, Ruby invokes this singleton_method_added
hook when the hook
method itself is first defined. Here is another use of the hook. In this
case, singleton_method_added
is defined as an
instance method of any class that includes a module. It is notified of
any singleton methods added to instances of that class:
# Including this module in a class prevents instances of that class # from having singleton methods added to them. Any singleton methods added # are immediately removed again. module Strict def singleton_method_added(name) STDERR.puts "Warning: singleton #{name} added to a Strict object" eigenclass = class << self; self; end eigenclass.class_eval { remove_method name } end end
In addition to method_added
and
singleton_method_added
, there are
hooks for tracking when instance methods and singleton methods are
removed or undefined. When an instance method is removed or undefined on
a class or module, the class methods method_removed
and method_undefined
are invoked on that module.
When a singleton method is removed or undefined on an object, the
methods singleton_method_removed
and singleton_method_undefined
are invoked on that
object.
Finally, note that the method_missing
and const_missing
methods documented elsewhere in this chapter also behave like
hook methods.
18.189.188.238