Diferença entre uma classe e um módulo

437

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 modulee quando você usa um, e por que usar um modulesobre um class?

Josh Moore
fonte

Respostas:

398

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

scottru
fonte
7
O módulo é o mesmo que Interfaces em java?
Saad Rehman Shah,
14
@Caffeine não é realmente porque os módulos de Ruby realmente incluir implementações, enquanto interfaces em Java são abstratos
Jorge Israel Peña
8
Não, Módulos e Java Packages / JARs são bestas completamente diferentes.
precisa
9
Eu sou mais como classes abstratas com implementação de métodos.
Automatico
2
Na verdade, o @Chole se depara com uma das coisas legais dos módulos: namespacing. Assim, enquanto módulos não são um equivalente direto para pacotes em Java, ele pode ser usado para alcançar algo semelhante: blog.rubybestpractices.com/posts/gregory/...
michaelok
513
╔═══════════════╦═══════════════════════════╦═════════════════════════════════╗
║               ║ 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)          ║
╚═══════════════╩═══════════════════════════╩═════════════════════════════════╝
Sergii Shevchyk
fonte
Qual é a superclasse da classe 'Class'?
Aashish P
10
Eu tenho a hierarquia, Classe -> Módulo -> Objeto -> BasicObject. Legal!!
Aashish P
Por que "module consiste em" omitir variáveis, quando classes e módulos suportam variáveis ​​de classe? Ver resposta aceita para stackoverflow.com/questions/5690458/...
kaleidic
Muitos diagramas em todas essas respostas. Um pequeno exemplo: rubyfiddle.com/riddles/06081
Donato
16
Como um módulo "não pode ser instanciado" e ainda possui métodos de instância?
Devius # 7/15
91

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 Mathclasse em Java. Você não a instancia e reutiliza os métodos na classe estática (por exemplo Math.random()).

Linan
fonte
11
Mas os módulos também podem adicionar métodos de instância à classe incluindo, enquanto classes estáticas em Java não podem.
Reintegrar Monica - notmaynard
4
Essa afirmação também é verdadeira, proveniente de um background C # pesado.
Damon Drake
5
Isso não é inteiramente verdade; módulos não têm métodos estáticos, apenas métodos. Os módulos podem "se estender" (a sintaxe é realmente extend self), disponibilizando seus métodos para a selfmetaclasse de suas. Isso torna possível despachar um método como random()em um Mathmó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.
usar o seguinte código
Eu diria que os módulos são mais semelhantes às interfaces com métodos em si (Java 8 interfaces com impl padrão) mas não se pode herdar de outra interfaces Java ao contrário
divideByZero
Como esta resposta tem tantos votos? btw que foi dito em palavras melhores 1mo antes: stackoverflow.com/a/17027346/986862
Andre Figueiredo
39

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

furacão
fonte
Sim, é assim que funciona. Como tal, os módulos não são comparáveis ​​às classes "estáticas" do Java; superclasse proxy (alguns chamam de um "metaclass") torna-se o receptor de mensagens método de envio do módulo, o que torna -o mais comparável a uma classe estática em Java, e os seus métodos de trabalho como métodos estáticos. O mesmo é verdade, no entanto, para as classes do Ruby, que podem adotar métodos do tipo "estático" inserindo extenduma classe. Na verdade, Ruby não faz distinção entre os métodos "instância" e "classe / estática", apenas os receptores deles.
precisa saber é o seguinte
7

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

Boris Stitnicky
fonte
6

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)

apadana
fonte
“- métodos de acesso: use. operador - constantes de acesso: use :: symbol ”somente esta resposta mencionou isso!
Qiulang
4

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.

QI Sayed
fonte
1

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

prasanthrubyist
fonte
0

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

Donato
fonte