The most commonly used reflective methods are those for determining the type of an object—what class it is an instance of and what methods it responds to. We introduced most of these important methods early in this book in Object Class and Object Type. To review:
o.class
c.superclass
o.instance_of? c
o.is_a? c
Determines whether o
is an
instance of c
, or of any of its
subclasses. If c
is a module,
this method tests whether o.class
(or any of its ancestors)
includes the module.
o.kind_of? c
c === o
For any class or module c
, determines if o.is_a?(c)
.
o.respond_to? name
Determines whether the object o
has a public or protected method with
the specified name. Pass true
as the second argument to check private methods as well.
In addition to these methods that you’ve already seen, there are a few related reflective methods for determining the ancestors of a class or module and for determining which modules are included by a class or module. These methods are easy to understand when demonstrated:
module A; end # Empty module module B; include A; end; # Module B includes A class C; include B; end; # Class C includes module B C < B # => true: C includes B B < A # => true: B includes A C < A # => true Fixnum < Integer # => true: all fixnums are integers Integer < Comparable # => true: integers are comparable Integer < Fixnum # => false: not all integers are fixnums String < Numeric # => nil: strings are not numbers A.ancestors # => [A] B.ancestors # => [B, A] C.ancestors # => [C, B, A, Object, Kernel] String.ancestors # => [String, Enumerable, Comparable, Object, Kernel] # Note: in Ruby 1.9 String is no longer Enumerable C.include?(B) # => true C.include?(A) # => true B.include?(A) # => true A.include?(A) # => false A.include?(B) # => false A.included_modules # => [] B.included_modules # => [A] C.included_modules # => [B, A, Kernel]
This code demonstrates include?
, which is a public instance method defined by the Module
class. But it also features two
invocations of the include
method
(without the question mark), which is a private instance method of
Module
. As a private method, it can
only be invoked implicitly on self
,
which restricts its usage to the body of a class
or module
definition. This use of the method
include
as if it were a keyword is
a metaprogramming example in Ruby’s core syntax.
A method related to the private include
method is the public Object.extend
. This method extends an object
by making the instance methods of each of the specified modules into
singleton methods of the object:
module Greeter; def hi; "hello"; end; end # A silly module s = "string object" s.extend(Greeter) # Add hi as a singleton method to s s.hi # => "hello" String.extend(Greeter) # Add hi as a class method of String String.hi # => "hello"
The class method Module.nesting
is not related to module inclusion or ancestry; instead,
it returns an array that specifies the nesting of modules at the
current location. Module.nesting[0]
is the current class
or module, Module.nesting[1]
is the
containing class or module, and so on:
module M class C Module.nesting # => [M::C, M] end end
Classes and modules are instances of the Class
and Module
classes. As such, you can create them
dynamically:
M = Module.new # Define a new module M C = Class.new # Define a new class C D = Class.new(C) { # Define a subclass of C include M # that includes module M } D.to_s # => "D": class gets constant name by magic
One nice feature of Ruby is that when a dynamically created
anonymous module or class is assigned to a constant, the name of that
constant is used as the name of the module or class (and is returned
by its name
and to_s
methods).
18.220.174.191