GGistDev

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)
  • prepend puts a module before the class; include puts 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