Ruby Singleton Ancestors
The singleton class sits in the lookup path before the real class. Its place there explains how class methods pass down to subclasses.
The singleton superclass verdict
A bird singleton class has Bird as its superclass. The equality check prints true.
class Bird
end
bird = Bird.new
puts bird.singleton_class.superclass == BirdA subclass inherits class methods
Vehicle defines kind as a class method. Car answers it, and the singleton superclass verdict prints true.
class Vehicle
def self.kind
puts "Vehicle kind"
end
end
class Car < Vehicle
end
Car.kind
puts Car.singleton_class.superclass == Vehicle.singleton_classAsking a chain with include?
The ancestors of a dog singleton class hold the singleton class itself and Dog. They do not hold Array, so the last verdict prints false.
class Dog
end
dog = Dog.new
chain = dog.singleton_class.ancestors
puts chain.include?(dog.singleton_class)
puts chain.include?(Dog)
puts chain.include?(Array)The singleton method wins the lookup
Dog defines greet for every dog. One dog defines its own greet, and that singleton version answers first.
class Dog
def greet
puts "Hello from Dog"
end
end
dog = Dog.new
other = Dog.new
def dog.greet
puts "Hello from this dog"
end
dog.greet
other.greetExample
class Shape
def self.label
puts "Shape label"
end
end
class Square < Shape
end
Square.label
puts Square.singleton_class.superclass == Shape.singleton_class
puts Square.singleton_class.ancestors.include?(Shape.singleton_class)Key points
- The singleton class of an object comes first in its lookup path.
- The superclass of an instance singleton class is the real class.
- The singleton class of a subclass has the singleton class of the parent as its superclass.
- That link is why a subclass answers the class methods of its parent.
- ancestors.include? proves a class sits in a chain without printing the chain.
In this example, Square answers the label class method defined on Shape. The superclass verdict shows the singleton class of Square points at the singleton class of Shape. The include verdict confirms that same link inside the ancestors chain.
Note
A printed chain would carry singleton class shapes, so these programs ask verdicts instead.
Try it Yourself
Edit the code, then press Run.
Running is simulated
Exercise
Why does a subclass answer the class methods of its parent?