Skip to content
Inheritance and super
step 1/7

Reading — step 1 of 7

Learn

~2 min readInheritance and Method Lookup

Ruby is single-inheritance — one parent class, but unlimited included modules. The Pickaxe treats this as Ruby's superpower: clean inheritance, plus module mixins for cross-cutting reuse.

Single inheritance

class Animal
  attr_reader :name
  def initialize(name)
    @name = name
  end
  def speak
    "generic sound"
  end
end

class Dog < Animal
  def speak
    "woof!"
  end
end

Dog.new("Rex").speak     # => "woof!"
Dog.new("Rex").name      # => "Rex" (inherited)

< is the inheritance operator. Dog < Animal reads "Dog inherits from Animal."

super — calling the parent

super invokes the same-named method on the superclass:

class Animal
  def initialize(name)
    @name = name
  end
end

class Dog < Animal
  def initialize(name, breed)
    super(name)         # calls Animal#initialize(name)
    @breed = breed
  end
end

Three forms of super:

  • super (no parens) — passes ALL the same args you received
  • super(x, y) — passes specific args
  • super() — passes nothing (empty parens explicitly)

The distinction matters: bare super is the default and the most common.

The Method Lookup Chain (ancestor chain)

When you call obj.foo, Ruby walks an ordered chain looking for foo:

  1. The object's singleton class (any methods defined on this specific instance)
  2. The object's class
  3. Modules included by the class, in REVERSE order of inclusion
  4. The superclass
  5. Modules included by the superclass, in reverse
  6. ... repeat up to BasicObject
  7. method_missing if nothing found
module M1; def hi; "M1 hi"; end; end
module M2; def hi; "M2 hi"; end; end

class Base; def hi; "Base hi"; end; end

class Child < Base
  include M1
  include M2     # later includes come EARLIER in the chain
end

Child.new.hi              # => "M2 hi"
Child.ancestors
# => [Child, M2, M1, Base, Object, Kernel, BasicObject]

ancestors is your debugging tool. When something behaves mysteriously, ClassName.ancestors shows you exactly what method-lookup will check.

Class methods and inheritance

Class methods (defined with self.method or class << self) are inherited too:

class Base
  def self.greet
    "hello from #{self}"
  end
end

class Child < Base; end
Child.greet      # => "hello from Child" — self is Child!

In class methods, self is the class itself — and inherited class methods see the calling class as self. Subtly powerful.

Common mistakes

  • Forgetting super in initialize — parent's setup doesn't run, instance variables uninitialized.
  • super vs super() — bare super passes args; super() passes none. Different behavior.
  • Multiple inheritance — Ruby doesn't have it. Use module mixins instead.
  • Reopening a class accidentallyclass Foo either creates OR re-opens. If a class with that name already exists, you're modifying it. Use namespaces.

Discussion

Ask a question, share an insight, or help someone who’s stuck.

Sign in to post a comment or reply.

Loading…