Reading — step 1 of 7
Learn
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 receivedsuper(x, y)— passes specific argssuper()— 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:
- The object's singleton class (any methods defined on this specific instance)
- The object's class
- Modules included by the class, in REVERSE order of inclusion
- The superclass
- Modules included by the superclass, in reverse
- ... repeat up to BasicObject
- 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.
supervssuper()— bare super passes args; super() passes none. Different behavior.- Multiple inheritance — Ruby doesn't have it. Use module mixins instead.
- Reopening a class accidentally —
class Fooeither 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…