Page MenuHomePhabricator

La communication entres objets
Updated 571 Days AgoPublic

Des objets en interaction

Parmi les exemples que nous avons évoqués précédemment, certaines décrivaient une interaction entre deux objets, comme le
feu qui en passant au vert permet à la voiture de démarrer. À l’instar de cette réalité observée, les objets en POO interagissent également. C’est en travaillant ensemble que les objets commencent à nous être utiles.

Tentons d’imaginer comment l’effet du changement de couleur du feu sur le démarrage de la voiture pourrait être reproduit par la POO. Considérons deux objets, feu-de-signalisation et voiture-vue-dans-la-rue, instances respectives des classes FeuRouge et Voiture. Ils sont caractérisés chacun par un attribut: l’entier couleur pour le feu et, pour la voiture, un entier vitesse. Faisons simple et supposons que le changement de couleur du feu indiquer à la voiture de changer sa vitesse de 0 à 50.

method.JPG (318×613 px, 30 KB)

La couleur du feu ne peut être modifiée que par la méthode change, c'est également le cas pour le changement de vitesse de la voiture qui relève exclusivement de la méthode changeVitesse. La seule manière pour deux objets de communiquer, c’est que l’un demande à l’autre d’exécuter une méthode qui lui est propre. Ici, le feu de rouge demande à la voiture d’exécuter sa méthode changeVitesse(50), qui porte à 50 son attribut vitesse. Vous constatez que le moyen utilisé par l’objet feu pour déclencher la méthode changeVitessse est l'utilisation d'une référence. Cette référence est dénommée voitureDevant et c'est sur celle-ci qu'il est déclenché la méthode changeVitesse.

Rappelez-vous qu’il est impropre que le feu se charge directement de modifier la variable vitesse de la voiture.

Le mode de communication entre deux objets correspond à la possibilité de déclencher une méthode définie dans la classe d'un autre objet. On appellera ce mécanisme de communication un envoi de message du premier objet vers le second.

Identification des destinataires de message

Il nous manque quelques éléments indispensables. Le premier est de signaler au feu que le référent voitureDevant est bien de classe Voiture. Afin de passer ce référent-là, on pourrait tout simplement le passer comme argument de la méthode change pour le feu. Cependant, nous rencontrerons bien plus souvent le procédé qui consiste à faire de ce référent un attribut à part entière de la classe FeuRouge, un attribut de type Voiture. Ces classes se définiront alors comme ceci:

class FeuRouge:
  def __init__(self):
    self.couleur = 1
    self.voitureDevant = None

  def nouvelleVoiture(self, voiture):
    self.voitureDevant = voiture

  def change(self):
    self.couleur = couleur + 1

    # Si le feu était rouge, on repasse au vert
    if self.couleur == 4: 
      self.couleur = 1

    # Si le feu est vert, et qu'on a une voiture devant
    if self.couleur == 1 and self.voitureDevant != None:
      self.voitureDevant.changeVitesse(50)

class Voiture:
  def __init__(self):
    self.vitesse = 0

  def changeVitesse(self, v):
    self.vitesse = v

Une association est ici réalisée entre les classes FeuRouge et Voiture et elle va dans le sens du Feu vers la Voiture. Cette association dirigée entre nos deux classes se représente en UML comme dans la figure ci-dessous. Ce diagramme indique que tout objet de la classe Feu se voit associé à un et un seul objet de la classe Voiture auquel il envoie le message changeVitesse. Le deuxième élément indispensable est de relier ce référent à l’objet en question et donc de lui affecter la même adresse physique que celle contenue dans le référent voiture-vue-dans-la-rue. Ici, nous utilisons donc la méthode nouvelleVoiture.

Une fois les classes décrites, notre programme de simulation de la route pourrait ressembler à quelque chose comme ceci:

feu_de_signalisation = FeuRouge() # Création de l'objet FeuRouge
voiture_vue_dans_la_rue = Voiture() # Création de l'objet Voiture

feu_de_signalisation.change() # Le feu passe à l'orange
feu_de_signalisation.change() # Le feu passe au rouge

# une voiture s'arrête devant le feu
feu_de_signalisation.nouvelleVoiture(voiture_vue_dans_la_rue) 

print(self.voiture_vue_dans_la_rue) 
feu_de_signalisation.change() # Le feu passe au vert
print(self.voiture_vue_dans_la_rue)
Au lieu d’envoyer un message du feu à toutes les voitures qui lui font face, il serait sans doute plus réaliste de considérer que les voitures sont susceptibles d’observer la transition de couleur du feu et de réagir en conséquence sans en recevoir explicitement l’ordre par le feu.

Exercice

  1. Écrivez une classe Policier représentant un agent des forces de l'ordre, une classe Criminel représentant une personne sur le point d'être arrêtée et une classe Menottes.
  2. Ajoutez une interaction entre Policier, Criminel et menotte à l'aide d'une communication par l'envoi de messages.
  3. Écrivez un programme qui instancie ces classes d'objet et qui effectue l'interaction entre eux.

Exercice 2

  1. Ecrivez une classe ATM qui représente un distributeur de billets, une classe personne, une classe billet de banque.
  2. Ajoutez une interaction où une personne retire de l’argent d’un distributeur
  3. Écrivez un programme qui instancie ces classes d'objet et qui effectue l'interaction entre eux.
solution
"""
Ecrivez une classe ATM qui représente un distributeur de billets, une classe personne, une classe billet de banque.
Ajoutez une interaction où une personne retire de l’argent d’un distributeur
Écrivez un programme qui instancie ces classes d'objet et qui effectue l'interaction entre eux.
"""
class Billet:
    def __init__(self, valeur):
        self.valeur: int = valeur
    def __str__(self):
        return str(self.valeur)

class ATM:
    def __init__(self):
        pass

    def imprimer(self, valeur: int) -> Billet:
        unBillet = Billet(valeur)
        return Billet(valeur)

    def avaler(self, billet: Billet):
        print("gnagnagna, j'ai mangé", billet)

class Personne:
    def __init__(self, argentEnBanque):
        self.cash: [Billet] = []
        self.banque = argentEnBanque

    def retirer(self, distrib: ATM, valeur: int):
        if self.banque >= valeur:
            billet = distrib.imprimer(valeur)
            self.cash.append(billet)
            self.banque -= valeur
        else:
            print("Erreur, vous n'avez pas assez d'argent!")

    def déposer(self, distrib: ATM, unBillet: Billet):
        try:
            # On recherche le billet de notre portefeuille
            position = self.cash.index(unBillet) # Index génère une erreur si le billet existe pas
            # On supprime la case "position" qui contient la position de "unBillet" dans notre portefeuille
            self.cash.pop(position)

            distrib.avaler(unBillet)
            self.banque += unBillet
        except:
            print("Le billet n'existe pas dans notre portefeuille")

    def __str__(self):
        ret = "Cette personne possède sur sois:"
        for i in self.cash:
            ret += str(i) + ", "
        ret += "et en banque: " + str(self.banque)
        return ret

steve = Personne(100)
distrib = ATM()

steve.retirer(distrib, 10)
print(steve)
Last Author
kossolax
Last Edited
Mar 10 2021, 7:51 PM