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.
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