Qual é a diferença entre uma classe e um módulo no Ruby? Nenhuma, uma classe é um módulo no Ruby:
Class.is_a?(Module) # => true
Não entendeu? Vamos ver com calma.
O que são módulos?
Um módulo pode ser definido de forma grosseira como uma coleção de métodos e constantes. Você encontrará dois tipos de métodos em um módulo: métodos de instância e métodos de módulo. Um método de módulo é aquele que pode ser executado sem a necessidade de que o módulo seja incluído em outro objeto:
module MeuModulo
def self.meu_metodo_de_modulo
puts "Sou um método de módulo!"
end
end
MeuModulo.meu_metodo_de_modulo # => Sou um método de módulo!
Por outro lado, métodos de instância, como o nome diz, precisam ser executados a partir de uma instância de um objeto. Módulos podem ser acoplados dentro de outros objetos, tornando assim estes métodos de instância acessíveis:
module MeuModulo
def meu_metodo_de_intancia
puts "Método de instância!"
end
end
class MinhaClasse
# Acoplando o MeuModulo
include MeuModulo
end
# Criando uma instância de MinhaClasse
minha_classe = MinhaClasse.new
# Executando o método de instância que foi criado em MeuModulo
puts minha_classe.meu_metodo_de_intancia # => Método de instância!
O que são classes?
Assim como os módulos, classes também são repositórios de métodos. Então qual é a diferença entre um e o outro?
Podemos ver claramente a diferença entre classes e módulos examinando o objeto Class mais de perto:
Class.superclass # => Module
Class.instance_methods(false)
# => ["superclass", "allocate", "new", "to_yaml"]
Como você pode ver no código acima, Class é uma subclasse de Module, mas com quatro métodos a mais. E é exatamente nestes métodos que encontraremos a resposta para a questão levantada acima.
Para esclarecer ainda mais, vamos imaginar como seria a classe Class implementada em Ruby:
class Class < Module
# Você já sabe como funciona o método new,
# já que o utilizamos o tempo todo
def initialize
end
# Devolve a superclasse da classe atual
def superclass
end
# Dá suporte ao método new
def allocate
end
def to_yaml
end
end
Os três primeiros métodos são responsáveis por permitir que você consiga criar uma instância de um objeto e trabalhar com o conceito de hierarquia de classes. O método to_yaml serve apenas como uma interface que dispara um erro do tipo TypeError caso ele não seja implementado por uma subclasse.
O método superclass é fácil de entender, já que a sua única finalidade é informar qual é a superclasse de um objeto. Se uma superclasse não for definida ele retornará nil.
Integer.superclass # => Numeric
Object.superclass # => nil
O método allocate é responsável por reservar um espaço na memória para a nova instância do objeto que estamos criando. O método devolve esta instância pronta.
E por último, o método initialize (new) tem duas funções. Primeiro ele executa o método allocate, que constrói um novo objeto da classe Class (ou de qualquer outra classe, afinal todas elas são subclasses de Class). Em seguida ele dispara o método initialize deste objeto, passando os argumentos para ele.
Finalizando
Se você chegou até aqui, então já entendeu as diferenças entre um módulo e uma classe em Ruby. Basta pensar que ambos são basicamente a mesma coisa (com estas significantes diferenças) e que quase tudo o que vale para um também vale para o outro.
A principal razão de existir estes dois tipos de objetos tão parecidos e ao mesmo tempo tão diferentes é que desta forma podemos deixar nosso código muito mais expressivo.
Normalmente você usará um módulo quando precisar incluí-lo em outro objeto ou usá-lo como um namespace. E você usará uma classe quando precisar de uma instância de um objeto ou utilizar o sistema de heranças. Cada um tem o seu propósito e você será o melhor sucedido se utilizar o recurso certo na hora certa.
Autor/Fonte: Nome do Jogo http://www.nomedojogo.com/