Inheritance in Ruby
Building class hierarchies with <, overriding behavior, and calling back up to the parent with super.
2 min read
Inheritance lets one class build on another, reusing its behavior and overriding only what needs to differ.
Basic inheritance
class Animal
def initialize(name)
@name = name
end
def speak
"#{@name} makes a sound."
end
end
class Dog < Animal
def speak
"#{@name} barks."
end
end
Dog.new("Rex").speak # "Rex barks."class Dog < Animal makes Dog a subclass of Animal. Dog inherits initialize and would inherit speak too, except speak is overridden here — Ruby always calls the most specific version defined for an object's actual class.
Calling the parent with super
Overriding a method often means extending it, not fully replacing it. super calls the same-named method on the parent class:
class Dog < Animal
def initialize(name, breed)
super(name) # calls Animal#initialize with `name`
@breed = breed
end
def speak
"#{super} Specifically, a bark." # calls Animal#speak, then appends text
end
endsuper with parentheses (super(name)) passes exactly the arguments you specify. Bare super with no parentheses (and no parens at all, not even empty ones) automatically forwards all of the current method's arguments — a subtle distinction that's caused more than one bug when someone assumed super meant "no arguments."
def initialize(name, breed)
super # forwards BOTH name and breed automatically
super() # forwards NOTHING -- calls Animal#initialize with no arguments
super(name) # forwards only `name`
endChecking the class hierarchy
Dog.superclass # Animal
Dog.ancestors # [Dog, Animal, Object, Kernel, BasicObject]
Dog.new("Rex").is_a?(Animal) # true -- Dog is-a AnimalEvery class in Ruby ultimately descends from Object (and BasicObject above that), which is why every object responds to methods like to_s, class, and inspect without you defining them.
Single inheritance, multiple mixins
Ruby only allows one direct superclass — class Dog < Animal < Mammal isn't valid syntax. When you need to share behavior across multiple unrelated hierarchies, that's what modules (from the previous lesson) are for; Dog.ancestors actually shows both the superclass chain and any mixed-in modules in the lookup order Ruby uses to resolve method calls.
When to reach for inheritance vs composition
Inheritance fits a genuine "is-a" relationship where a subclass really is a more specific version of its parent (Dog is-a Animal). If you find yourself overriding most of a parent's methods just to reuse a couple, or building a hierarchy that doesn't map to a clean specialization, favor composition instead — give the class an instance of the other object and delegate to it, rather than force a relationship that doesn't really fit. Ruby's flexibility makes deep inheritance chains easy to build, but that doesn't mean they age well.
Test what you just learned
4 quick questions. Get all of them right to unlock the next lesson.
You can take the quiz without an account — logging in just lets your result count toward your progress.