Polar Code 🎭

Command Palette

Search for a command to run...

10
Pièce N°10

Chapitre 10 : Programmation orientée objet (POO)

La brume enveloppait les docks, estompant les contours des grues comme des fantômes métalliques. J’attendais. Pas un contact, non. Une livraison. Un objet. Une entité autonome avec ses données et ses comportements. C’est ça, la POO. On ne pense plus en simples variables et fonctions, mais en agents. Chacun avec son rôle, ses secrets, ses protocoles.

Classes et objets

La classe, c’est le plan. Le schéma directeur. L’objet, c’est l’instance concrète, l’agent sur le terrain.

class Agent:
    """Classe définissant un agent opérationnel."""
    pass

# Création d'objets (instances)
ombre = Agent()
silencieux = Agent()

Une classe définit une catégorie d’êtres. Un objet en est une incarnation. ombre et silencieux sont deux agents distincts, mais construits sur le même modèle.

Constructeur (__init__)

C’est la méthode qui s’exécute à la naissance de l’objet. Son baptême. On y initialise ses attributs, son état initial.

class Agent:
    def __init__(self, nom_code, specialite, statut="actif"):
        self.nom_code = nom_code
        self.specialite = specialite
        self.statut = statut
        self.missions_accomplies = 0
        print(f"Agent {nom_code} initialisé. Spécialité: {specialite}")

# Instanciation avec le constructeur
fantome = Agent("Fantôme", "infiltration", "deep_cover")
vega = Agent("Vega", "cyber-intrusion")

Le self est la référence à l’objet lui-même. C’est par lui qu’il se connaît.

Attributs et méthodes

Les attributs sont les données de l’objet. Ses caractéristiques. Les méthodes sont ses actions, ses compétences.

class Agent:
    def __init__(self, nom_code, specialite):
        self.nom_code = nom_code          # Attribut
        self.specialite = specialite      # Attribut
        self._cachette = None             # Attribut "protégé" (convention)

    # Méthode : une action que l'agent peut effectuer
    def accomplir_mission(self, difficulte):
        """Exécute une mission et met à jour le statut."""
        print(f"{self.nom_code} exécute une mission (niveau {difficulte}).")
        # ... logique de mission ...
        self._mettre_a_jour_carnet()
        return "succès" if difficulte < 8 else "échec contrôlé"

    # Méthode "privée" (par convention)
    def _mettre_a_jour_carnet(self):
        """Méthode interne. Ne pas appeler de l'extérieur."""
        self.missions_accomplies += 1

# Utilisation
araignee = Agent("Araignée", "réseau")
resultat = araignee.accomplir_mission(5)
print(f"Missions accomplies: {araignee.missions_accomplies}")

L’objet sait des choses (attributs) et sait faire des choses (méthodes). Il est autonome.

Encapsulation

C’est le principe de la boîte noire. On cache l’état interne. On n’expose que ce qui est nécessaire.

class CompteOffshore:
    def __init__(self, id, devise="USD"):
        self._id = id                     # "Protégé"
        self._devise = devise
        self.__solde = 0                  # "Privé" (name mangling)
        self.__code_acces = self._generer_code()

    def deposer(self, montant):
        """Interface publique pour déposer."""
        if montant > 0:
            self.__solde += montant
            self.__logger(f"Dépôt: {montant} {self._devise}")
        return self.__solde

    def _generer_code(self):              # Méthode "protégée"
        import random
        return random.randint(10000, 99999)

    def __logger(self, message):          # Méthode "privée"
        # Log interne, invisible de l'extérieur
        with open(f"log_{self._id}.txt", "a") as f:
            f.write(message + "\n")

# Utilisation
compte_x = CompteOffshore("X9")
compte_x.deposer(50000)
# compte_x.__solde  # ERREUR : attribut privé, inaccessible.
# compte_x._generer_code()  # Possible, mais contre la convention.

L’encapsulation protège l’intégrité de l’objet. On ne laisse pas n’importe qui tripoter le solde du compte.

Héritage

Créer une classe enfant qui hérite des caractéristiques d’une classe parent, et qui peut les spécialiser.

class Agent:  # Classe parent
    def __init__(self, nom_code):
        self.nom_code = nom_code
        self.estime = 10

    def rapporter(self, information):
        print(f"[{self.nom_code}] Rapporte: {information}")

class Infiltre(Agent):  # Classe enfant
    def __init__(self, nom_code, couverture):
        super().__init__(nom_code)  # Appel du constructeur parent
        self.couverture = couverture
        self.penetration = 0

    # Surcharge de méthode (spécialisation)
    def rapporter(self, information, urgence=False):
        super().rapporter(information)  # Appel de la méthode parent
        if urgence:
            print(f"  -> Message prioritaire, extraction recommandée.")
        self.penetration += 1

# Utilisation
camaleon = Infiltre("Caméléon", "journaliste")
camaleon.rapporter("Le ministre a un compte en Suisse.", urgence=True)
print(f"Estime: {camaleon.estime}, Pénétration: {camaleon.penetration}")

L’héritage, c’est la transmission du savoir-faire. L’enfant a tout du parent, mais il peut faire plus, ou différemment.

Polymorphisme

Le même nom d’action, des comportements différents selon l’objet.

class Saboteur:
    def neutraliser(self):
        print("Désactive les systèmes physiques.")

class Hacker:
    def neutraliser(self):
        print("Corrompt les données et efface les logs.")

class Persuadeur:
    def neutraliser(self):
        print("Convainc la cible de se retirer.")

# Fonction qui utilise le polymorphisme
def executer_operation_nette(agent):
    """Prend n'importe quel agent ayant une méthode 'neutraliser'."""
    agent.neutraliser()

# Utilisation
equipe = [Saboteur(), Hacker(), Persuadeur()]
for agent in equipe:
    executer_operation_nette(agent)  # Chaque agent réagit à sa façon.

Le polymorphisme, c’est l’interchangeabilité. Vous donnez un ordre standard (neutraliser), et chaque type d’agent l’exécute avec ses moyens propres. Vous n’avez pas besoin de connaître les détails, seulement l’interface.

La silhouette est enfin apparue dans la brume. Un objet Courier, avec ses attributs (colis_scellé, itineraire_verrouillé) et ses méthodes (livrer(), confirmer_reception()). Il a accompli sa tâche sans que j’aie à savoir comment il avait traversé la ville. C’était un objet fiable, encapsulé, qui faisait son travail.

La POO, c’est modéliser le monde comme un réseau d’agents interactifs, chacun avec ses responsabilités, ses secrets, ses compétences. C’est la façon de penser des architectes. Des stratèges.

Et dans notre jeu, penser en objets, c’est rester en vie.


Le monde est un réseau d'objets. Soyez-en le maître.