Inheritance in Ruby
Single inheritance with a clear method lookup chain; use super to delegate.
Basics
Subclass with <, override methods, and call super to reuse parent behavior.
class Animal
def speak
"..."
end
end
class Dog < Animal
def speak
"woof " + super
end
end
Dog.new.speak # => "woof ..."
Method lookup and ancestors
Ruby searches the receiver’s class, then prepended modules, included modules, and superclasses.
Dog.ancestors
# => [Dog, Animal, Object, Kernel, BasicObject] (plus prepended/included modules if any)
prependputs a module before the class;includeputs it after the class but before superclasses.
initialize and super
Chain constructors; super forwards all args, super() forwards none, and super(a) forwards explicitly.
class Base
def initialize(a) @a = a end
end
class Sub < Base
def initialize(a, b)
super(a) # pass specific args up
@b = b
end
end
Overriding and extension
Override methods to specialize; call super to extend instead of replace.
class Logger
def write(msg) puts msg end
end
class PrefixedLogger < Logger
def write(msg)
super("[LOG] #{msg}")
end
end
Composition vs inheritance
Prefer composition when sharing behavior across unrelated types. Modules (mixins) often beat deep hierarchies.
module Persisted
def save; storage.write(id, to_h) end
end
class User
include Persisted
# composition: has-a storage rather than is-a Logger
def storage; @storage ||= Repo.new end
end
Visibility and protected methods
protected allows receivers of the same class (or subclasses) to call the method on each other, enabling comparisons.
class Box
def initialize(w) @w = w end
def heavier_than?(other) weight > other.weight end
protected
def weight = @w
end
Summary
- Ruby has single inheritance; mix in shared behavior with modules
- Use
super,super(), or explicit arguments to control delegation - Prefer composition/mixins to avoid deep, brittle hierarchies