Inheritance, super and Method Visibility

17.1 Inheritance

Ruby supports single inheritance only. Use modules for shared behavior.

super (bare) forwards all arguments. super() passes no arguments. super(a, b) passes specific ones.

class Animal
  attr_reader :name
  def initialize(name) = @name = name
  def speak = "..."
  def describe = "#{name} says #{speak}"
end

class Dog < Animal
  attr_reader :breed
  def initialize(name, breed)
    super(name)              # call the parent's initialize with explicit args
    @breed = breed
  end
  def speak = "Woof"
end

class Puppy < Dog
  def speak = "#{super} (squeaky)"    # bare super passes the same arguments
end

Puppy.new("Bit", "Lab").describe     # "Bit says Woof (squeaky)"
Puppy.superclass; Puppy.ancestors
Dog < Animal                          # true
Puppy.instance_method(:speak).owner

17.2 Method Visibility

Anywhere (default) Instances of the same class (or subclasses), with an explicit receiver allowed

Only within the object, without an explicit receiver (except self.setter=)

class Account
  def initialize(balance) = @balance = balance

  def transfer_to(other, amount)
    return false unless sufficient?(amount)
    other.receive(amount)          # protected: callable from the same class family
    @balance -= amount
  end

  def >(other) = balance > other.balance

  protected

  attr_reader :balance
  def receive(amount) = @balance += amount

  private

  def sufficient?(amount) = @balance >= amount
end
private def helper = :secret                  # inline form
private_class_method :new                     # e.g., for singletons/factories
public_send(:name)                            # respects visibility; send ignores it

17.3 Abstract Methods and Template Method

class Report
  def generate = [header, body, footer].join("\n")
  def header = "=== #{title} ==="
  def footer = "Generated #{Time.now}"
  def title = raise(NotImplementedError, "#{self.class} must implement title")
  def body = raise(NotImplementedError)
end

class SalesReport < Report
  def title = "Sales"
  def body = "Total: $1000"
end