Menu
Coddy logo textTech

Módulos e include

Parte da seção Programação orientada a objetos do Journey de Ruby da Coddy. Lição 27 de 57.

Um módulo é um grupo nomeado de métodos. Ele não pode criar objetos, mas uma classe pode usar include para incluí-lo, e então cada instância tem os métodos do módulo como se a classe os tivesse definido. Isso é chamado de 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

Saída:

Hello, I am Ada

Os métodos de um módulo podem chamar métodos fornecidos pela classe, como name acima. Portanto, um módulo pode servir a classes muito diferentes, desde que cada uma ofereça o que o módulo usa:

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

Saída:

Hello, I am R2
Hello, I am Paris

Uma classe tem apenas uma superclasse, mas pode incluir qualquer número de módulos. include? pergunta se uma classe inclui um módulo, e o módulo aparece em ancestors, logo após a classe, que é onde Ruby procura seus 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)

Saída:

swimming, flying
true
[Duck, Flyer, Swimmer]

Os módulos também agrupam classes e constantes relacionadas sob um único nome, um namespace, para que os nomes não entrem em conflito. Shop::Item e Game::Item são classes 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

Saída:

shop item, tax 0.2
0.2
challenge icon

Desafio

Fácil

Complete os módulos e as classes. Greetable#greet retorna Hello, I am Ada, usando o name do objeto. Walkable#walk(steps) adiciona steps a um contador mantido em @steps (começando com nil na primeira vez) e retorna Ada walked 30 steps, o total acumulado. Person inclui ambos os módulos; Robot inclui apenas Greetable e seu nome é R- seguido por um número de série.

O código fornecido cria uma pessoa e um robô a partir da primeira linha (Ada 7), depois executa os comandos greet p, greet r ou walk 10 (para a pessoa) e imprime cada resultado, e finalmente robot walks: false.

Seu código deve ser colocado em greetable.rb, walkable.rb, person.rb e robot.rb. main.rb contém o código de entrada/saída fornecido e não pode ser editado.

Experimente você mesmo

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

# Código de entrada/saída fornecido: mantenha-o 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 iconTeste seus conhecimentos

Esta lição inclui um quiz rápido. Comece a lição para respondê-lo e acompanhar seu progresso.

Todas as lições de Programação orientada a objetos

Pratique por conta própria: Compilador de Ruby online