Différence entre une classe et un module

438

Je viens de Java et maintenant je travaille davantage avec Ruby.

Une fonctionnalité linguistique que je ne connais pas est la module. Je me demande ce qu'est exactement un moduleet quand en utilisez-vous un, et pourquoi utiliser un modulesur un class?

Josh Moore
la source

Réponses:

398

La première réponse est bonne et donne des réponses structurelles, mais une autre approche consiste à réfléchir à ce que vous faites. Les modules visent à fournir des méthodes que vous pouvez utiliser dans plusieurs classes - pensez-y comme des "bibliothèques" (comme vous le verriez dans une application Rails). Les cours portent sur des objets; les modules concernent les fonctions.

Par exemple, les systèmes d'authentification et d'autorisation sont de bons exemples de modules. Les systèmes d'authentification fonctionnent sur plusieurs classes au niveau de l'application (les utilisateurs sont authentifiés, les sessions gèrent l'authentification, de nombreuses autres classes agiront différemment en fonction de l'état d'authentification), de sorte que les systèmes d'authentification agissent comme des API partagées.

Vous pouvez également utiliser un module lorsque vous avez partagé des méthodes entre plusieurs applications (encore une fois, le modèle de bibliothèque est bon ici).

scottru
la source
7
Le module est-il le même que les interfaces en java?
Saad Rehman Shah
14
@Caffeine pas vraiment parce que les modules Ruby incluent des implémentations, alors que les interfaces en Java sont abstraites
Jorge Israel Peña
8
Non, les modules et les packages / JAR Java sont des bêtes complètement différentes.
Karoly Horvath
9
Je suis plus comme des classes abstraites avec implémentation de méthode.
Automatico
2
En fait, @Chole trouve l'une des bonnes choses à propos des modules: l'espace de noms. Ainsi, bien que les modules ne soient pas un équivalent direct des packages en Java, ils peuvent être utilisés pour réaliser quelque chose de similaire: 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
la source
Quelle est la superclasse de la classe 'Class'?
Aashish P
10
J'ai obtenu la hiérarchie, Classe -> Module -> Objet -> BasicObject. Cool!!
Aashish P
Pourquoi le «module se compose de» omet des variables, alors que les classes et les modules prennent tous les deux en charge les variables de classe? Voir la réponse acceptée à stackoverflow.com/questions/5690458/…
kaleidic
Beaucoup de diagrammes dans toutes ces réponses. Un petit exemple en cours d'exécution: rubyfiddle.com/riddles/06081
Donato
16
Comment un module "ne peut-il pas être instancié" tout en ayant des méthodes d'instance?
devius
91

Je suis surpris que personne ne l'ait pas encore dit.

Étant donné que le demandeur vient d'un arrière-plan Java (et moi aussi), voici une analogie qui aide.

Les classes sont tout simplement comme les classes Java.

Les modules sont comme des classes statiques Java. Pensez à la Mathclasse en Java. Vous ne l'instanciez pas et vous réutilisez les méthodes de la classe statique (par exemple Math.random()).

Linan
la source
11
Mais les modules peuvent également ajouter des méthodes d'instance à la classe notamment, contrairement aux classes statiques en Java.
Rétablir Monica - notmaynard
4
Cette affirmation est également vraie provenant d'un arrière-plan lourd C #.
Damon Drake
5
Ce n'est pas tout à fait vrai; les modules n'ont pas de méthodes statiques, ils ont juste des méthodes. Les modules peuvent "s'étendre" (la syntaxe est en fait extend self), rendant leurs méthodes disponibles à leur selfmétaclasse. Cela permet de répartir une méthode comme random()sur un Mathmodule. Mais de par leur nature, les méthodes d'un module ne peuvent pas être appelées seules self. Cela a à voir avec la notion de Ruby self, ses métaclasses et comment fonctionne la recherche de méthode. Consultez "Metaprogramming Ruby" - Paolo Perlotta pour plus de détails.
scottburton11
Je dirais que les modules sont plus similaires aux interfaces avec des méthodes (interfaces Java 8 avec implication par défaut) mais ne peuvent pas hériter les uns des autres contrairement aux interfaces java
divideByZero
Comment cette réponse a-t-elle autant de votes? btw qui a été dit avec de meilleurs mots 1 mois auparavant: stackoverflow.com/a/17027346/986862
Andre Figueiredo
39

Fondamentalement, le module ne peut pas être instancié. Lorsqu'une classe comprend un module, une superclasse proxy est générée qui donne accès à toutes les méthodes de module ainsi qu'aux méthodes de classe.

Un module peut être inclus par plusieurs classes. Les modules ne peuvent pas être hérités, mais ce modèle "mixin" fournit un type utile d '"héritage multiple". Les puristes OO seront en désaccord avec cette affirmation, mais ne laissez pas la pureté entraver le travail.


(Cette réponse était liée à l'origine http://www.rubycentral.com/pickaxe/classes.html, mais ce lien et son domaine ne sont plus actifs.)

ouragan
la source
Oui, c'est comme ça que ça marche. En tant que tels, les modules ne sont pas comparables aux classes "statiques" de Java; la superclasse proxy (certains appellent cela une « méta - classe ») devient le récepteur des messages d'expédition de la méthode du module, ce qui rend ce plus comparable à une classe statique en Java, et ses méthodes fonctionnent comme des méthodes statiques. Il en va de même, cependant, pour les classes de Ruby, qui peuvent adopter des méthodes de type "statique" en intégrant extendune classe. Ruby ne fait aucune distinction entre les méthodes "instance" et "classe / statique", seulement leurs destinataires.
scottburton11
7

Moduledans Ruby, dans une certaine mesure, correspond à la classe abstraite Java - a des méthodes d'instance, les classes peuvent en hériter (via include, les gars de Ruby l'appellent un "mixin"), mais n'ont pas d'instances. Il existe d'autres différences mineures, mais cette quantité d'informations est suffisante pour vous aider à démarrer.

Boris Stitnicky
la source
6

namespace: les modules sont des namespaces ... qui n'existent pas en java;)

Je suis également passé de Java et python à Ruby, je me souviens que j'avais exactement cette même question ...

La réponse la plus simple est donc que le module est un espace de noms, qui n'existe pas en Java. En java, l'état d'esprit le plus proche de l'espace de noms est un package .

Donc, un module en rubis est comme quoi en java:
classe? Pas d'
interface? Pas de
classe abstraite? Pas de
colis? Oui peut-être)

méthodes statiques à l'intérieur des classes en java: identiques aux méthodes à l'intérieur des modules en ruby

En java, l'unité minimale est une classe, vous ne pouvez pas avoir de fonction en dehors d'une classe. Cependant en rubis c'est possible (comme python).

Alors, qu'est-ce qui entre dans un module?
classes, méthodes, constantes. Le module les protège sous cet espace de noms.

Aucune instance: les modules ne peuvent pas être utilisés pour créer des instances

Ins mixtes: parfois, les modèles d'héritage ne sont pas bons pour les classes, mais en termes de fonctionnalités, vous voulez regrouper un ensemble de classes / méthodes / constantes ensemble

Règles concernant les modules dans ruby:
- Les noms des modules sont UpperCamelCase
- les constantes dans les modules sont ALL CAPS (cette règle est la même pour toutes les constantes ruby, non spécifiques aux modules)
- méthodes d'accès: utilisation. opérateur
- constantes d'accès: use :: symbol

exemple simple d'un module:

module MySampleModule
  CONST1 = "some constant"

  def self.method_one(arg1)
    arg1 + 2
  end
end

comment utiliser les méthodes à l'intérieur d'un module:

puts MySampleModule.method_one(1) # prints: 3

comment utiliser les constantes d'un module:

puts MySampleModule::CONST1 # prints: some constant

Quelques autres conventions sur les modules:
utilisez un module dans un fichier (comme les classes ruby, une classe par fichier ruby)

apadana
la source
«- méthodes d'accès: utilisation. opérateur - constantes d'accès: utilisez :: symbole »seule cette réponse en fait mention!
Qiulang
4

Bottom line: Un module est un croisement entre une classe statique / utilitaire et un mixin.

Les mixins sont des éléments réutilisables d'implémentation "partielle", qui peuvent être combinés (ou composés) de façon mix & match, pour aider à écrire de nouvelles classes. Ces classes peuvent en outre avoir leur propre état et / ou code, bien sûr.

IQ Sayed
la source
1

Classe

Lorsque vous définissez une classe, vous définissez un plan directeur pour un type de données. la classe contient des données, possède une méthode qui interagit avec ces données et est utilisée pour instancier des objets.

Module

  • Les modules sont un moyen de regrouper des méthodes, des classes et des constantes.

  • Les modules vous offrent deux avantages majeurs:

    => Les modules fournissent un espace de noms et empêchent les conflits de noms. L'espace de noms permet d'éviter les conflits avec les fonctions et les classes portant le même nom qui ont été écrites par quelqu'un d'autre.

    => Les modules implémentent le mixin.

(y compris Module dans Klazz donne aux instances de Klazz un accès aux méthodes Module.)

(étendre Klazz avec Mod donnant à la classe Klazz l'accès aux méthodes Mods.)

prasanthrubyist
la source
0

Tout d'abord, quelques similitudes qui n'ont pas encore été mentionnées. Ruby prend en charge les classes ouvertes, mais les modules sont également ouverts. Après tout, Class hérite de Module dans la chaîne d'héritage de classe et donc Class et Module ont un comportement similaire.

Mais vous devez vous demander quel est le but d'avoir à la fois une classe et un module dans un langage de programmation? Une classe est destinée à être un plan directeur pour la création d'instances, et chaque instance est une variation réalisée du plan directeur. Une instance n'est qu'une variation réalisée d'un plan (la classe). Naturellement, les classes fonctionnent comme des créations d'objets. De plus, comme nous voulons parfois qu'un plan dérive d'un autre plan, les classes sont conçues pour prendre en charge l'héritage.

Les modules ne peuvent pas être instanciés, ne créent pas d'objets et ne prennent pas en charge l'héritage. N'oubliez donc pas qu'un module n'hérite PAS d'un autre!

Alors, quel est l'intérêt d'avoir des modules dans une langue? Une utilisation évidente des modules est de créer un espace de noms, et vous le remarquerez également avec d'autres langues. Encore une fois, ce qui est cool avec Ruby, c'est que les modules peuvent être rouverts (tout comme les classes). Et c'est une grande utilisation lorsque vous souhaitez réutiliser un espace de noms dans différents fichiers 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

Mais il n'y a pas d'héritage entre les modules:

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>

Le module Apple n'a hérité d'aucune méthode du module Green et lorsque nous avons inclus Apple dans la classe Fruit, les méthodes du module Apple sont ajoutées à la chaîne d'ancêtres des instances Apple, mais pas les méthodes du module Green, même si le Green module a été défini dans le module Apple.

Alors, comment pouvons-nous accéder à la méthode verte? Vous devez l'inclure explicitement dans votre classe:

class Fruit
  include Apple::Green
end
 => Fruit 
 > f.green
=> green

Mais Ruby a une autre utilisation importante des modules. Il s'agit de l'installation Mixin, que je décris dans une autre réponse sur SO. Mais pour résumer, les mixins vous permettent de définir des méthodes dans la chaîne d'héritage des objets. Grâce aux mixins, vous pouvez ajouter des méthodes à la chaîne d'héritage des instances d'objet (include) ou à la singleton_class de self (extend).

Donato
la source