Eu vim de Java e agora estou trabalhando mais com Ruby.
Um recurso de idioma com o qual não estou familiarizado é o module
. Gostaria de saber o que exatamente é um module
e quando você usa um, e por que usar um module
sobre um class
?
Eu vim de Java e agora estou trabalhando mais com Ruby.
Um recurso de idioma com o qual não estou familiarizado é o module
. Gostaria de saber o que exatamente é um module
e quando você usa um, e por que usar um module
sobre um class
?
Respostas:
A primeira resposta é boa e fornece algumas respostas estruturais, mas outra abordagem é pensar no que você está fazendo. Os módulos são sobre o fornecimento de métodos que você pode usar em várias classes - pense neles como "bibliotecas" (como você veria em um aplicativo Rails). Classes são sobre objetos; módulos são sobre funções.
Por exemplo, sistemas de autenticação e autorização são bons exemplos de módulos. Os sistemas de autenticação funcionam em várias classes no nível do aplicativo (os usuários são autenticados, as sessões gerenciam a autenticação, muitas outras classes agem de maneira diferente com base no estado de autenticação); portanto, os sistemas de autenticação agem como APIs compartilhadas.
Você também pode usar um módulo quando tiver compartilhado métodos em vários aplicativos (novamente, o modelo da biblioteca é bom aqui).
╔═══════════════╦═══════════════════════════╦═════════════════════════════════╗
║ ║ class ║ module ║
╠═══════════════╬═══════════════════════════╬═════════════════════════════════╣
║ instantiation ║ can be instantiated ║ can *not* be instantiated ║
╟───────────────╫───────────────────────────╫─────────────────────────────────╢
║ usage ║ object creation ║ mixin facility. provide ║
║ ║ ║ a namespace. ║
╟───────────────╫───────────────────────────╫─────────────────────────────────╢
║ superclass ║ module ║ object ║
╟───────────────╫───────────────────────────╫─────────────────────────────────╢
║ methods ║ class methods and ║ module methods and ║
║ ║ instance methods ║ instance methods ║
╟───────────────╫───────────────────────────╫─────────────────────────────────╢
║ inheritance ║ inherits behaviour and can║ No inheritance ║
║ ║ be base for inheritance ║ ║
╟───────────────╫───────────────────────────╫─────────────────────────────────╢
║ inclusion ║ cannot be included ║ can be included in classes and ║
║ ║ ║ modules by using the include ║
║ ║ ║ command (includes all ║
║ ║ ║ instance methods as instance ║
║ ║ ║ methods in a class/module) ║
╟───────────────╫───────────────────────────╫─────────────────────────────────╢
║ extension ║ can not extend with ║ module can extend instance by ║
║ ║ extend command ║ using extend command (extends ║
║ ║ (only with inheritance) ║ given instance with singleton ║
║ ║ ║ methods from module) ║
╚═══════════════╩═══════════════════════════╩═════════════════════════════════╝
Estou surpreso que alguém não tenha dito isso ainda.
Como o solicitante veio de um plano de fundo Java (e eu também), aqui está uma analogia que ajuda.
Classes são simplesmente como classes Java.
Os módulos são como classes estáticas Java. Pense em Math
classe em Java. Você não a instancia e reutiliza os métodos na classe estática (por exemplo Math.random()
).
extend self
), disponibilizando seus métodos para a self
metaclasse de suas. Isso torna possível despachar um método como random()
em um Math
módulo. Mas, por sua natureza, os métodos de um módulo não podem ser chamados por conta própria self
. Isso tem a ver com a noção de Ruby de self
, suas metaclasses e como a pesquisa de métodos funciona. Confira "Metaprogramming Ruby" - Paolo Perlotta para obter detalhes.
Basicamente, o módulo não pode ser instanciado. Quando uma classe inclui um módulo, é gerada uma superclasse de proxy que fornece acesso a todos os métodos do módulo, bem como aos métodos da classe.
Um módulo pode ser incluído por várias classes. Os módulos não podem ser herdados, mas esse modelo "mixin" fornece um tipo útil de "herança múltipla". Os puristas de OO discordam dessa afirmação, mas não deixam a pureza atrapalhar o trabalho.
(Esta resposta foi originalmente vinculada a http://www.rubycentral.com/pickaxe/classes.html
, mas esse link e seu domínio não estão mais ativos.)
extend
uma classe. Na verdade, Ruby não faz distinção entre os métodos "instância" e "classe / estática", apenas os receptores deles.
Module
em Ruby, até certo ponto, corresponde à classe abstrata Java - possui métodos de instância, classes podem herdar dela (via include
, os caras do Ruby chamam de "mixin"), mas não possui instâncias. Existem outras pequenas diferenças, mas essas informações são suficientes para você começar.
namespace: os módulos são namespaces ... que não existem em java;)
Também mudei de Java e python para Ruby, lembro-me de ter exatamente a mesma pergunta ...
Portanto, a resposta mais simples é que o módulo é um espaço para nome, que não existe em Java. Em java, a mentalidade mais próxima do espaço para nome é um pacote .
Portanto, um módulo em ruby é como o que em java:
class? Nenhuma
interface? Não há
aula abstrata? Sem
pacote? Sim talvez)
métodos estáticos dentro de classes em java: o mesmo que métodos dentro de módulos em ruby
Em java, a unidade mínima é uma classe, você não pode ter uma função fora de uma classe. No entanto, em ruby isso é possível (como python).
Então, o que se passa em um módulo?
classes, métodos, constantes. O módulo os protege nesse espaço de nome.
Nenhuma instância: módulos não podem ser usados para criar instâncias
Entradas mistas: às vezes os modelos de herança não são bons para as classes, mas em termos de funcionalidade, queremos agrupar um conjunto de classes / métodos / constantes
Regras sobre módulos em ruby:
- Os nomes dos módulos são UpperCamelCase
- as constantes nos módulos são ALL CAPS (esta regra é a mesma para todas as constantes em ruby, não específicas para os módulos)
- métodos de acesso: use. operador
- constantes de acesso: use :: symbol
exemplo simples de um módulo:
module MySampleModule
CONST1 = "some constant"
def self.method_one(arg1)
arg1 + 2
end
end
como usar métodos dentro de um módulo:
puts MySampleModule.method_one(1) # prints: 3
como usar constantes de um módulo:
puts MySampleModule::CONST1 # prints: some constant
Algumas outras convenções sobre módulos:
Use um módulo em um arquivo (como classes ruby, uma classe por arquivo ruby)
Conclusão: Um módulo é um cruzamento entre uma classe estática / utilitário e um mixin.
Os mixins são peças reutilizáveis de implementação "parcial", que podem ser combinadas (ou compostas) de uma forma combinada, para ajudar a escrever novas classes. Essas classes também podem ter seu próprio estado e / ou código, é claro.
Classe
Ao definir uma classe, você define um blueprint para um tipo de dados. dados de retenção de classe, possuem um método que interage com esses dados e são usados para instanciar objetos.
Módulo
Módulos são uma maneira de agrupar métodos, classes e constantes.
Os módulos oferecem dois grandes benefícios:
=> Os módulos fornecem um espaço para nome e evitam conflitos de nomes. O espaço para nome ajuda a evitar conflitos com funções e classes com o mesmo nome que foram escritas por outra pessoa.
=> Módulos implementam a instalação de mixin.
(incluir o Módulo no Klazz fornece instâncias do Klazz acesso aos métodos do Módulo.)
(estenda o Klazz com o Mod, dando à classe Klazz acesso aos métodos Mods.)
Primeiro, algumas semelhanças que ainda não foram mencionadas. O Ruby suporta classes abertas, mas os módulos também são abertos. Afinal, Class herda de Module na cadeia de herança Class e, portanto, Class e Module têm algum comportamento semelhante.
Mas você precisa se perguntar qual é o propósito de ter tanto uma classe quanto um módulo em uma linguagem de programação? Uma classe pretende ser um blueprint para a criação de instâncias, e cada instância é uma variação realizada do blueprint. Uma instância é apenas uma variação realizada de um blueprint (a Classe). Naturalmente, as Classes funcionam como criação de objeto. Além disso, como às vezes queremos que um modelo derive de outro, as Classes são projetadas para suportar a herança.
Os módulos não podem ser instanciados, não criam objetos e não suportam herança. Portanto, lembre-se de que um módulo NÃO herda de outro!
Então, qual é o sentido de ter Módulos em um idioma? Um uso óbvio dos módulos é criar um espaço para nome e você perceberá isso com outros idiomas também. Novamente, o interessante do Ruby é que os módulos podem ser reabertos (assim como as classes). E esse é um grande uso quando você deseja reutilizar um espaço para nome em diferentes arquivos Ruby:
module Apple
def a
puts 'a'
end
end
module Apple
def b
puts 'b'
end
end
class Fruit
include Apple
end
> f = Fruit.new
=> #<Fruit:0x007fe90c527c98>
> f.a
=> a
> f.b
=> b
Mas não há herança entre os módulos:
module Apple
module Green
def green
puts 'green'
end
end
end
class Fruit
include Apple
end
> f = Fruit.new
=> #<Fruit:0x007fe90c462420>
> f.green
NoMethodError: undefined method `green' for #<Fruit:0x007fe90c462420>
O módulo Apple não herdou nenhum método do módulo Green e, quando incluímos Apple na classe Fruit, os métodos do módulo Apple são adicionados à cadeia ancestral das instâncias da Apple, mas não os métodos do módulo Green, mesmo que o Green O módulo foi definido no módulo Apple.
Então, como obtemos acesso ao método verde? Você deve incluí-lo explicitamente em sua classe:
class Fruit
include Apple::Green
end
=> Fruit
> f.green
=> green
Mas Ruby tem outro uso importante para os módulos. Esta é a instalação Mixin, que descrevo em outra resposta no SO. Mas, para resumir, os mixins permitem definir métodos na cadeia de herança de objetos. Por meio de mixins, você pode adicionar métodos à cadeia de herança de instâncias de objetos (include) ou à singleton_class of self (extend).