Modules

Les blocs de code sont pratiques pour l’organiser. On a vu les blocs basiques, les classes, les méthodes… Voici les modules. Ce sont des blocs qui peuvent contenir des constantes et des méthodes qui ont un lien entre elles. Les modules permettent surtout d’éviter des conflits entre des constantes (ou des méthodes) qui porteraient le même nom.

Petit exemple : imaginons que je veuille gérer des équipes de foot et des équipes de basket. Il y a des :

  • similitudes : dans les deux sports, le système de score est identique (3pts/1pt/0pt pour respectivement victoire/nul/défaite) et les équipes ont un nom de club (et même si tout ceci n’est pas forcément exact, ça le sera dans mon exemple!)
  • différences : le ballon, le nombre de joueurs…

Je vais donc créér des méthodes qui seront communes aux deux sports, mais au lieu de les réécrire, je vais les importer dans chacune des deux classes.

module Equipe
  def initialize(club,score,matches)
    @nom = club
    @score = score
    @matches = matches
  end
  def victoire
    @score += 3
    @matches += 1
  end
  def nul
    @score += 1
    @matches += 1
  end
  def defaite
    @score += 0
    @matches += 1
  end
  attr_reader :score
  attr_writer :score
  def statut
    puts "En " + @matches.to_s + " matches, l'équipe a engrangé " + @score.to_s + " points."
  end
end
 
class Football
  include Equipe
  def ballon
    puts "Au foot, on joue avec un ballon en cuir!"
  end
  def joueurs
    puts "Au foot, on joue à 11 contre 11."
  end
end
 
class Basket
  include Equipe
  def ballon
    puts "Au basket, on joue avec un ballon orange Spalding!"
  end
  def joueurs
    puts "Au basket, on joue à 5 contre 5."
  end
end
 
girondins = Football.new("Girondins",0,0)
girondins.victoire
girondins.victoire
girondins.victoire
girondins.defaite
girondins.nul
girondins.victoire
girondins.victoire
girondins.statut
girondins.ballon
bulls = Basket.new("Chicago Bulls",0,0)
bulls.defaite
bulls.defaite
bulls.defaite
bulls.defaite
bulls.nul
bulls.nul
bulls.nul
bulls.statut
bulls.ballon
→ En 7 matches, l'équipe a engrangé 16 points.
→ Au foot, on joue avec un ballon en cuir!
→ En 7 matches, l'équipe a engrangé 3 points.
→ Au basket, on joue avec un ballon orange Spalding!

Je crée un module Equipe qui comprend des méthodes communes aux deux sports : outre l’initialisation, il y a le calcul du score. Puis je crée 2 classes (une pour chaque sport) où j’importe le module Equipe (et toutes ses méthodes avec) et où je définis des méthodes qui affichent des phrases différentes pour chaque sport.
Ensuite je crée un objet Football sans appeler le module Equipe (étant donné qu’il est indirectement appelé via la classe Football). Puis sur mon objet “girondins”, je peux appeler des méthodes du module Equipe ET de la classe Football. Je fais pareil pour une équipe de basket où j’appelle les mêmes méthodes.

Attention : j’ai nommé à l’identique des méthodes de Football et des méthodes de Basket alors que ce ne sont pas les mêmes. Il y a sans doute une meilleure façon d’écrire ça. J’écris les exemples parfois sans que ce soit dans un contexte optimal ou pertinent, le but étant avant tout de voir comment ça marche, d’avoir un début de mise en situation.

Organiser son code dans plusieurs fichiers

Si on commence à avoir une grande quantité de code (ou bien par souci de segmentation poussée du code), on va diviser son code dans plusieurs fichiers, et les appeler séparément. Ca peut être pratique d’un point de vue de maintenance.

Deux méthodes pour importer :

  • load : le fichier est importé sans condition (donc, à chaque fois qu’on l’appelle)
  • require : le fichier est importé une seule fois (cela permet d’éviter les duplicatas)

Voici la syntaxe :

load "mon_fichier_ruby.rb"
require "mon_autre_fichier.rb"

Le chemin peut être relatif ou absolu.
L’avantage du “require” est que l’on peut mettre des conditions, des boucles, des variables etc. dans le chemin, alors que “load” ne le permet pas. Conditions, boucles… intéressant. On voit ça demain!