web-dev-qa-db-fra.com

Différence entre une classe et un module

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

Une fonction linguistique que je ne connais pas bien est la module. Je me demande en quoi consiste exactement un module et quand en utilisez-vous un, et pourquoi utiliser un module par rapport à un class?

423
Josh Moore

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 - considérez-les comme des "bibliothèques" (comme dans une application Rails). Les classes concernent les 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 agissent différemment en fonction de l'état auth), 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).

388
scottru
╔═══════════════╦═══════════════════════════╦═════════════════════════════════╗
║               ║ 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)          ║
╚═══════════════╩═══════════════════════════╩═════════════════════════════════╝
504
Sergii Shevchyk

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

Le demandeur étant issu d'un contexte Java (et moi-même), voici une analogie qui aide.

Les classes ressemblent simplement à Java classes.

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

86
Linan

En gros, le module ne peut pas être instancié. Lorsqu'une classe comprend un module, une superclasse de proxy est générée et permet d'accéder à toutes les méthodes du module ainsi qu'à celles de la 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 de "multiple héritage". Les puristes OO seront en désaccord avec cette affirmation, mais ne laissez pas la pureté entraver votre 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.)

39
hurcane

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

7
Boris Stitnicky

espace de noms: les modules sont des espaces de noms ... qui n'existent pas dans Java;)

J'ai aussi passé de Java et python à Ruby, je me souviens bien de la même question ...

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

Donc, un module dans Ruby ressemble à quoi en Java:
classe? Non
interface? Non
classe abstraite? Non
package? Oui (peut-être)

méthodes statiques dans les classes en Java: identiques aux méthodes dans les modules en Ruby

Dans Java l'unité minimale est une classe, vous ne pouvez pas avoir de fonction en dehors d'une classe. Cependant, dans Ruby, cela est possible (comme avec 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

Mixed ins: Parfois, les modèles d'héritage ne conviennent pas aux classes, mais en termes de fonctionnalités, ils souhaitent regrouper un ensemble de classes/méthodes/constantes.

Règles concernant les modules en Ruby:
- Les noms de 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écifique aux modules)
- méthodes d'accès: utiliser. opérateur
- constantes d'accès: use :: symbol

exemple simple de module:

module MySampleModule
  CONST1 = "some constant"

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

comment utiliser des 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:
Utiliser un module dans un fichier (comme Ruby classes, une classe par fichier Ruby)

5
apadana

Ligne de fond: un module est un croisement entre une classe statique/utilitaire et un mixin.

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

4
IQ Sayed

Classe

Lorsque vous définissez une classe, vous définissez un plan pour un type de données. class hold data, ont une méthode qui interagit avec ces données et est utilisée pour instancier des objets.

Module

  • Les modules permettent de regrouper des méthodes, des classes et des constantes.

  • Les modules vous apportent deux avantages majeurs:

    => Les modules fournissent un espace de noms et empêchent les conflits de noms. Les espaces de noms aident à éviter les conflits avec des fonctions et des classes du même nom écrites par quelqu'un d'autre.

    => Les modules implémentent la fonction mixin.

(notamment Module dans Klazz donne aux instances Klazz accès aux méthodes Module.)

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

1
prasanthrubyist

Tout d'abord, certaines similitudes qui n'ont pas encore été mentionnées. Ruby supporte les classes ouvertes, mais les modules sont aussi ouverts. Après tout, Class hérite de Module dans la chaîne d'héritage de classe et ainsi, 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 censée être un modèle pour la création d'instances, et chaque instance est une variante réalisée du modèle. Une instance est juste une variation réalisée d'un plan (la classe). Naturellement, les classes fonctionnent comme une création d’objet. De plus, comme nous souhaitons parfois qu’un modèle soit dérivé d’un autre, 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. Alors rappelez-vous 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 bien avec Ruby, c'est que les modules peuvent être rouverts (tout comme les classes). Et ceci est un gros usage 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'hérite d'aucune méthode du module Green. Lorsque nous avons inclus Apple dans la classe Fruit, les méthodes du module Apple sont ajoutées à la chaîne ancêtre d'instances Apple, mais pas de méthodes du module Green, même si le module Green 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. Ceci est l'installation Mixin, que je décris dans une autre réponse sur SO. Mais pour résumer, mixins vous permet de définir des méthodes dans la chaîne d'objets d'héritage. Grâce à mixins, vous pouvez ajouter des méthodes à la chaîne d'héritage d'instances d'objet (include) ou à la classe singleton_class de self (extend).

0
Donato