Introspection And Singleton Classes in Ruby
The ideas of Introspection (also known as Reflection) and Singleton Classes (also known as Eigenclasses or Metaclasses) are essential to Ruby’s dynamic and metaprogramming capabilities. This article provides a thorough explanation of these concepts.
Introspection (Reflection)
A program’s introspection is its capacity to analyze its own structure and state while it is running. It enables a Ruby program to dynamically query data about classes, objects, and methods. Writing code that creates or changes other code while it is running is known as metaprogramming, and it is frequently linked to the capacity for introspection.
Numerous methods that are mostly defined by Kernel, Object, and Module make up the core reflection API.
You can also read Embedding Ruby: Running Ruby Code Inside C & C++ Programs
Introspecting Object Types and Ancestry
An object’s class hierarchy can be discovered via introspection techniques:
| Method | Description | Code Example |
| Object#class | Returns the class of the object. | s = "Hello"; s.class ⇒ String |
| Object#is_a? / kind_of? | Checks if the object is an instance of a given class or one of its superclasses. | num = 1; num.kind_of? Numeric ⇒ true |
| Object#instance_of? | Returns true only if the object is an instance of the exact specified class. | num = 1; num.instance_of? Numeric ⇒ false |
| Module#ancestors | Lists the inheritance chain (classes and included modules) of a class. | C.ancestors ⇒ [C, B, A, Object,...] |
| Module#superclass | Returns the direct superclass of a class. | C.superclass ⇒ A |
Introspecting Methods
You may find out what methods an object or class supports by querying it:
| Method | Description | Code Example |
| Object#methods / Object#public_methods | Returns an array of symbols (Ruby 1.9) or strings (Ruby 1.8) listing the methods available to an object. | f.methods.sort ⇒ [...] :bar, ..., :yay] |
| Object#singleton_methods | Returns an array of names of methods defined exclusively on that object (its singleton methods). | o.singleton_methods ⇒ ["single"] |
| Module#instance_methods | Lists instance methods defined by a class (and optionally inherited methods by passing false). | C.instance_methods(false) ⇒ [:c] |
| Object#respond_to? | Checks whether an object can respond to a specific method name. | s.respond_to?(:upcase) ⇒ true |
| Object#method | Returns a callable Method object bound to the receiver. | 1.method(:succ).call ⇒ 2 |
Introspecting Variables
To examine an object’s or class’s instance and class variables, Ruby offers reflective methods:
| Method | Description | Code Example |
| Object#instance_variables | Returns an array of instance variable names (symbols/strings) for the receiver. | f.instance_variables ⇒ [:@bar] |
| Object#instance_variable_get | Retrieves the value of a named instance variable. | f.instance_variable_get(:@bar) ⇒ 42 |
| Object#instance_variable_set | Sets the value of a named instance variable (violates encapsulation, typically discouraged externally). | f.instance_variable_set(:@bar, 17) ⇒ 17 |
| Module#class_variable_get | Retrieves the value of a named class variable (@@). | Foo.class_variable_get(:@@instances) ⇒ 8 |
You can also read What Are The Ruby Version Management With Code Examples
Singleton Classes (Eigenclasses)
A singleton method is one that is only available to one instance of the same class and is defined on a single object. Class methods are a subset of singleton methods in which the object is the actual Class object.
Definition and Role
In reality, an object’s singleton methods are instance methods of an implicit, anonymous class that is only connected to that particular object.
- This anonymous class is called the Eigenclass, Metaclass, or Singleton Class.
- Each object has a unique singleton class that is generated automatically.
- The singleton class inherits from the ordinary class of the object and is positioned between it and its actual class.
You can also read What Are The XML And RSS Processing In Ruby With Examples
Defining Singleton Methods (Class Methods)
Singleton methods can be defined using a variety of syntactic conventions:
Direct Definition (Simple Singleton Method)
Using def object.method_name defines a method available only to that specific object.
Code Example: Instance Singleton Method
class Thing
end
thing1 = Thing.new
thing2 = Thing.new
def thing1.makestuff
puts "I belong to thing one"
end
thing1.makestuff # Works
begin
thing2.makestuff # Will raise NoMethodError
rescue NoMethodError
puts "thing2 does NOT have makestuff"
end
Output
I belong to thing one
thing2 does NOT have makestuff
The class << object Idiom (Opening the Singleton Class/Eigenclass)
This approach allows you to define class methods or add numerous methods to the object’s eigenclass, or singleton class. Class methods are defined when it is used to a class name (class << Point, for example).
Code Example: Defining Class Methods via class << self
The term “self” in a class definition refers to the actual class.
class Point
attr_accessor :x, :y
def initialize(x, y)
@x = x
@y = y
end
# Open the eigenclass to define class methods
class << self
# Class method that sums multiple Point objects
def sum(*points)
total_x = points.sum(&:x)
total_y = points.sum(&:y)
Point.new(total_x, total_y)
end
end
end
# Example usage
p1 = Point.new(2, 3)
p2 = Point.new(4, 1)
p3 = Point.new(1, 6)
result = Point.sum(p1, p2, p3)
puts "Sum: (#{result.x}, #{result.y})"
Output
Sum: (7, 10)
Accessing the Singleton Class
These days, Object#singleton_class is used to retrieve an object’s singleton class. As an alternative, self is returned inside the class << object block by the traditional idiom:
object = "hello"
# Direct way
puts object.singleton_class
# Classic idiom for getting the singleton class
singleton_class = class << object
self # returns the singleton class of 'object'
end
puts singleton_class
Output
#<Class:#<String:0x000072c0af88e7e8>>
#<Class:#<String:0x000072c0af88e7e8>>
Message Propagation (Method Lookup)
In method lookup, the first step is determined by the singleton class’s existence. Ruby handles resolution when a method is called on an object (o.m) by verifying:
- For singleton methods named
m, the objecto‘s eigenclass (singleton class). The eigenclass’s superclasses are also looked up if the item is a class. - The instance method called
m‘s class ofo. - The class of
o‘s instance methods for any modules that are included (starting with the most recent module included). - The ancestor chain extends to BasicObject and Object.
Ruby calls the original receiver’smethod_missingmethod if the method cannot be located.
You can also read Date And Time Manipulation In Ruby With Code Examples
