Menu
Coddy logo textTech

Módulos e inclusión

Parte de la sección Programación orientada a objetos del Journey de Ruby de Coddy. Lección 27 de 57.

Un módulo es un grupo con nombre de métodos. No puede crear objetos, pero una clase puede includelo, y entonces cada instancia tiene los métodos del módulo como si la clase los hubiera definido. Esto se denomina 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

Salida:

Hello, I am Ada

Los métodos de un módulo pueden llamar a métodos que la clase proporciona, como name arriba. Por lo tanto, un módulo puede servir para clases muy diferentes, siempre que cada una ofrezca lo que el módulo utiliza:

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

Salida:

Hello, I am R2
Hello, I am Paris

Una clase tiene una sola superclase, pero puede incluir cualquier cantidad de módulos. include? pregunta si una clase incluye un módulo, y el módulo aparece en ancestors, justo después de la clase, que es donde Ruby busca sus métodos:

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)

Salida:

swimming, flying
true
[Duck, Flyer, Swimmer]

Los módulos también agrupan clases y constantes relacionadas bajo un mismo nombre, un espacio de nombres, para que los nombres no entren en conflicto. Shop::Item y Game::Item son clases diferentes:

module Shop
  TAX = 0.2

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

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

Salida:

shop item, tax 0.2
0.2
challenge icon

Desafío

Fácil

Completa los módulos y las clases. Greetable#greet devuelve Hello, I am Ada, usando el name del objeto. Walkable#walk(steps) suma los pasos a un contador almacenado en @steps (que comienza con nil la primera vez) y devuelve Ada walked 30 steps, el total acumulado. Person incluye ambos módulos; Robot incluye únicamente Greetable y su nombre es R- seguido de un número de serie.

El código proporcionado crea una persona y un robot a partir de la primera línea (Ada 7), luego ejecuta los comandos greet p, greet r o walk 10 (para la persona) e imprime cada resultado, y finalmente robot walks: false.

Tu código debe ir en greetable.rb, walkable.rb, person.rb y robot.rb. main.rb contiene el código proporcionado de entrada/salida y no se puede editar.

Pruébalo tú mismo

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

# Código de entrada/salida suministrado: déjalo tal como está
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 iconPonte a prueba

Esta lección incluye un breve cuestionario. Empieza la lección para responderlo y registrar tu progreso.

Todas las lecciones de Programación orientada a objetos

Practica por tu cuenta: Compilador de Ruby online