Menu
Coddy logo textTech

Modules and include

Part of the Object Oriented Programming section of Coddy's Ruby journey. Lesson 27 of 57.

A module is a named group of methods. It cannot create objects, but a class can include it, and then every instance has the module's methods as if the class defined them. This is called a mixin:

module Greetable
  def greet
    "Hello, I am #{name}"
  end
end

class Person
  include Greetable
  attr_reader :name

  def initialize(name)
    @name = name
  end
end

puts Person.new("Ada").greet

Output:

Hello, I am Ada

A module's methods can call methods the class provides, such as name above. So one module can serve very different classes, as long as each offers what the module uses:

module Greetable
  def greet
    "Hello, I am #{name}"
  end
end

class Robot
  include Greetable

  def name
    "R2"
  end
end

class City
  include Greetable

  def name
    "Paris"
  end
end

puts Robot.new.greet
puts City.new.greet

Output:

Hello, I am R2
Hello, I am Paris

A class has only one superclass but can include any number of modules. include? asks whether a class includes a module, and the module shows up in ancestors, right after the class, which is where Ruby looks for its methods:

module Swimmer
  def swim
    "swimming"
  end
end

module Flyer
  def fly
    "flying"
  end
end

class Duck
  include Swimmer
  include Flyer
end

d = Duck.new
puts "#{d.swim}, #{d.fly}"
puts Duck.include?(Flyer)
p Duck.ancestors.take(3)

Output:

swimming, flying
true
[Duck, Flyer, Swimmer]

Modules also group related classes and constants under one name, a namespace, so that names do not clash. Shop::Item and Game::Item are different classes:

module Shop
  TAX = 0.2

  class Item
    def label
      "shop item, tax #{TAX}"
    end
  end
end

puts Shop::Item.new.label
puts Shop::TAX

Output:

shop item, tax 0.2
0.2
challenge icon

Challenge

Easy

Complete the modules and classes. Greetable#greet returns Hello, I am Ada, using the object's name. Walkable#walk(steps) adds steps to a counter kept in @steps (starting from nil the first time) and returns Ada walked 30 steps, the running total. Person includes both modules; Robot includes only Greetable and its name is R- followed by a serial number.

The supplied code creates a person and a robot from the first line (Ada 7), then runs commands greet p, greet r or walk 10 (for the person) and prints each result, and finally robot walks: false.

Your code goes in greetable.rb, walkable.rb, person.rb and robot.rb. main.rb holds the supplied input/output code and cannot be edited.

Try it yourself

require_relative 'greetable'
require_relative 'walkable'
require_relative 'person'
require_relative 'robot'

# Supplied input/output code: keep it as it is
input = []
while (line = gets)
  input << line.chomp
end
name, serial = input[0].split
person = Person.new(name)
robot = Robot.new(serial)
input.drop(1).each do |line|
  command, arg = line.split
  if command == "walk"
    puts person.walk(arg.to_i)
  else
    target = arg == "p" ? person : robot
    puts target.greet
  end
end
puts "robot walks: #{Robot.include?(Walkable)}"
quiz iconTest yourself

This lesson includes a short quiz. Start the lesson to answer it and track your progress.

All lessons in Object Oriented Programming

Practice on your own: Online Ruby compiler