Un seul mot, module, pour deux outils différents.One word, module, for two different tools.
Le Vol 5 ouvre la question : d'où un objet tient-il son comportement ? Et la réponse de Ruby commence par le module — un mot qui recouvre deux usages qu'on confond souvent. Premier rôle : ranger. Un module est un espace de noms qui regroupe constantes et classes sous un préfixe, pour éviter les collisions (Billing::Invoice n'est pas Shipping::Invoice). Second rôle : partager. Un module mixé dans une classe par include y injecte ses méthodes, comme un héritage de capacité. Même mot, deux intentions — et tout le volume commence par les distinguer.Vol 5 opens the question: where does an object get its behavior? And Ruby's answer starts with the module — one word covering two uses we often conflate. First role: organizing. A module is a namespace grouping constants and classes under a prefix, to avoid collisions (Billing::Invoice isn't Shipping::Invoice). Second role: sharing. A module mixed into a class via include injects its methods, like an inheritance of capability. Same word, two intentions — and the whole volume begins by telling them apart.
module Billing # 1) un ESPACE DE NOMS : il range TAX = 0.2 class Invoice; end # Billing::Invoice, pas la même qu'ailleurs end module Greetable # 2) un MIXIN : il partage du comportement def greet = "Bonjour, #{name}" end Billing::TAX # => 0.2 on RANGE et on accède via :: class User include Greetable # on PARTAGE : greet entre dans User attr_reader :name def initialize(n) = @name = n end User.new("Ada").greet # => "Bonjour, Ada"
Billing::Invoice
→ greet injecté
À gauche, on accède de l'extérieur avec :: : le module reste un tiroir. À droite, on l'aspire dans une classe avec include : ses méthodes deviennent celles de la classe. Le même module, selon qu'on le nomme ou qu'on l'inclut.On the left, you access it from outside with ::: the module stays a drawer. On the right, you pull it into a class with include: its methods become the class's own. The same module, depending on whether you name it or include it.
« Est-ce que je veux ranger sous un préfixe, ou partager un comportement ? » Si c'est ranger, on garde le module dehors et on y accède par ::. Si c'est partager, on l'include. Confondre les deux, c'est aspirer dans sa classe tout un module dont on ne voulait qu'une constante."Do I want to organize under a prefix, or share a behavior?" If organizing, keep the module outside and reach it via ::. If sharing, include it. Conflating the two pulls a whole module into your class when you wanted just one constant.
On ne peut pas faire Greetable.new : un module ne s'instancie pas, et n'a pas de superclasse. C'est justement ce qui le rend mixable sans limite là où l'héritage est simple. Il reste pourtant un objet (Vol 1) — Greetable.class répond Module, et Class hérite d'ailleurs de Module. Une classe, c'est un module qui sait s'instancier.You can't do Greetable.new: a module isn't instantiable, and has no superclass. That's exactly what makes it mixable without limit where inheritance is single. It's still an object (Vol 1) — Greetable.class answers Module, and Class in fact inherits from Module. A class is a module that can instantiate.