Módulos e Mixins

Módulos Ruby são similares a classes em relação ao fato de que também armazenam uma coleção de métodos, constantes e outras definições de módulos e classes. Módulos são definidos de forma similar as classes, mas a palavra-chave module é usada no lugar de class. Entretanto, diferente das classes, você não pode criar objetos baseados em módulos nem pode criar módulos que herdam desse módulo; ao invés disso, você especifica qual funcionalidade de um módulo específico você deseja adicionar a uma classe ou a um objeto específico. Módulos permanecem sozinhos; não há hierarquia de módulos ou herança. Módulos são um bom lugar para armazenar constantes em um local centralizado.

Módulos tem dois principais objetivos:

 1   # p058mytrig.rb
 2   module Trig
 3     PI = 3.1416
 4     # métodos de classe
 5     def Trig.sin(x)
 6       # ...
 7     end
 8     def Trig.cos(x)
 9       # ...
10     end
11   end
12 
13   # p059mymoral.rb
14   module Moral
15     VERY_BAD = 0
16     BAD         = 1
17     def Moral.sin(badness)
18       # ...
19     end
20   end
21 
22   # p060usemodule.rb
23   require 'p058mytrig'
24   require 'p059mymoral'
25   Trig.sin(Trig::PI/4)
26   Moral.sin(Moral::VERY_BAD)
 1   # p061mixins.rb
 2   module D
 3     def initialize(nome)
 4       @nome =nome
 5     end
 6     def to_s
 7       @nome
 8     end
 9   end
10 
11   module Debug
12     include D
13     # Métodos que agem como perguntas
14     # geralmente são nomeados com um ? no final
15     def quem_sou_eu?
16       "#{self.class.nome} (\##{self.object_id}): #{self.to_s}"
17     end
18   end
19 
20   class Phonograph
21     # a declaração include apenas faz uma referência para o módulo nomeado
22     # se esse módulo está em um arquivo separado, use require para adicioná-lo
23     # antes de usar o include
24     include Debug
25     # ...
26   end
27 
28   class EightTrack
29     include Debug
30     # ...
31   end
32 
33   ph = Phonograph.new("West End Blues")
34   et = EightTrack.new("Real Pillow")
35   puts ph.quem_sou_eu?
36   puts et.quem_sou_eu?

Observe como usamos require ou load. require e load aceitam strings como argumentos.

require ‘motorcycle’ ou load ‘motorcycle.rb’

include recebe o nome de um módulo, na forma de uma constante, como em include Coisa.

O método include aceita qualquer número de módulos para serem inclusos:

include Enumerable, Comparable

Embora toda classe seja um módulo, o método include não permite que uma classe seja incluída em outra classe.

Mais alguns exemplos:

 1   #  p062stuff.rb
 2   #  Um módulo pode conter constantes, métodos e classes.
 3   #  Mas não pode conter instâncias
 4 
 5   module Coisa
 6     C = 10
 7     def Coisa.m(x)  # prefixe com o nome do módulo para um método de classe
 8       C*x
 9     end
10     def p(x)        # um método de instância, um mixin para outras classes
11       C + x
12     end
13     class T
14       @t = 2
15     end
16   end
17   puts Coisa::C     # namespace Coisa
18   puts Coisa.m(3)   # como um método de classe
19   x = Coisa::T.new
20   # se você tentar o seguinte terá um erro de constante não inicializada
21   # puts C
22 
23   #------------
24 
25   # p063stuffusage.rb
26   require 'p062stuff'     # carrega o módulo Coisa do arquivo p062stuff.rb
27                       # $: é uma variável de sistema - contém o caminho para carregamento de arquivos
28 
29   class D
30     include Coisa     # se refere ao módulo carregado
31     puts Coisa.m(4)
32   end
33 
34   d = D.new
35   puts d.p(5)         # método p do módulo Coisa
36   puts $:             # array de diretórios para procurar carregamentos
37   $: << "c:/"         # adicione um diretório ao loadpath
38   puts $:
39   puts Coisa.m(5)     # método de classe Coisa não chamado pelo objeto D

Lembre-se que você pode incluir mais de um módulo em uma classe. Porém, uma classe não pode herdar de mais de uma classe.
Nomes de classe geralmente são substantivos, enquanto nomes de módulos costumam ser adjetivos.

NO RAILS: O Código fonte do Rails usa bastante módulos, em particular a técnica de reabrir o corpo de definição tanto de módulos quanto de classes.

Logo do Guru-SP

Este material tem como base o tutorial do RubyLearning.com de Satish Talim e foi traduzido por membros do GURU-SP com a permissão do autor.

Ajude o RubyLearning participando em algum dos cursos pagos ou fazendo uma doação para o projeto

Voltar para o índice