Le principe de base de la programmation objet est la représentation de tout concept sous la forme d'une classe, c'est à dire par un ensemble d'attributs et de méthodes.
Les attributs décrivent les différentes propriétés du concept et contiennent des données. Ils servent donc à mémoriser l'information que l'on possède à un moment donné sur ce concept. Pour vous rattacher à ce que nous avons déjà vu (ou autrement dit à la programmation procédurale), vous pouvez voir les attributs comme un ensemble de variables de différents types.
Les méthodes, quand à elles, représentent les opérations que l'on peut effectuer sur ce concept. Ce sont à peu de chose près des sous-programmes, mis à part qu'ils sont associés à la classe représentant le concept.
Dans cette première partie du cours, nous allons voir le strict minimum nécessaire pour déclarer une classe dans un programme Python. D'où le titre "Déclaration basique d'une classe".
Pour introduire la notion de classe nous prendrons comme exemple le concept de voiture. Pour simplifier, nous nous intéresserons uniquement à deux propriétés d'une voiture: son immatriculation et son compteur. Ces deux propriétés seront représentées dans la classe Voiture par deux attributs:
Nous définirons trois méthodes pour cette classe:
Le schéma suivant résume très sommairement la représentation de la classe:
Voilà comment la classe Voiture pourrait être déclarée en Python (pour ne pas tout de suite rentrer dans les détails, j'ai ommis le code figurant dans le corps des méthodes):
class Voiture : def ChangerPneu (self) : .... def Rouler (self, Km) : .... def AfficherAttributs(self) : ....
Le principe est assez simple: le mot clé class est suivi du nom de la classe. Ensuite, on a l'ensemble des méthodes de la classe. D'un point de vue syntaxique, il n'y a aucune différence entre la déclaration d'une méthode et la déclaration d'un sous-programme, mis à part qu'une méthode possède toujours au moins un paramètre jouant un rôle particulier. Dans l'exemple, ci-dessus il s'agit du pramètre self. Sa signification sera expliquée plus loin.
En programmation objet, il y a les classes et les objets. Pour comprendre intuitivement la différence entre classe et objet, vous pouvez comparer une classe à un moule à gâteau et les objets à différents gâteaux réalisés à l'aide de ce moule.
Dès lors qu'une classe a été déclarée, le moule existe et il devient possible de créer des objets à l'aide de cette classe. Ce procédé est appelé l'instanciation. Chaque objet créé à partir d'une classe est une instance de cette classe.
En Python, l'instanciation se fait par l'intermédiaire d'un sous-programme de même nom que la classe. Dans notre exemple, l'instruction suivante:
LaVoiture = Voiture ( )
a pour effet de créer un objet de la classe Voiture et de stocker son identifiant dans la variable LaVoiture.
Lorsqu'un objet a été créé, il est possible de le "manipuler" de deux manières:
Un attribut d'un objet se note par le nom de l'objet, suivi d'un point, suivi du nom de l'attribut. Par exemple LaVoiture.Compteur, désigne l'attribut Compteur de l'objet LaVoiture.
Un attribut s'utilise comme une variable. On peut donc en particulier affecter une valeur à un attribut. Exemple:
LaVoiture.Compteur = 10000
met la valeur 10000 dans l'attribut Compteur de l'objet LaVoiture.
Rappelons qu'en Python, une variable est créée lorsqu'on lui affecte une valeur pour la première fois. De même, un attribut d'une classe est créé dès qu'on lui affecte une valeur. Il ne sera donc pas utilisable avant.
Cela implique donc que les attributs d'une classe ne sont pas définis avant l'exécution du programme qui l'utilise. C'est l'exécution de ce programme qui créé les attributs.
Nous avions dit que les méthodes sont comparables à des sous-programmes, mais il y a quelques différences entre ces deux concepts. Premièrement, l'application d'une méthode à un objet ne s'écrit pas comme un appel de sous-programme. Par exemple, pour faire rouler LaVoiture de 10km, on écrirait:
LaVoiture.Rouler (10)
Pour appliquer une méthode à un objet, on écrit donc le nom de l'objet, suivi d'un point, suivi du nom de la méthode avec ses paramètres effectifs entre parenthèses.
Deuxièmement, dans les parenthèses on ne donne pas la valeur du paramètre effectif correspondant au premier paramètre formel. Dans notre exemple, nous avons nommé ce paramètre self (nous prendrons d'ailleurs cette convention dans toute la suite du cours).
En fait, ce paramètre effectif est l'objet auquel on applique la méthode (la variable LaVoiture dans l'exemple précédent). Comme il figure avant le point, on ne le remet pas dans les parenthèses.
Avant d'aller plus loin dans les explications, présentons le projet qui nous servira d'exemple (il s'agit du projet Voiture1 que vous trouverez dans le répertoire Exemple/Exemple-Python-ProgObjet1). Voici les choix affichés par la boucle de saisie des données:
Le choix Nouvelle Voiture créé une nouvelle instance de la classe Voiture, en demandant son immatriculation à l'utilisateur.
Le choix Rouler augmente le compteur par la distance indiquée par l'utilisateur sauf si le compteur atteind ou dépasse 10000 km. Dans ce cas, le programme affiche un message indiquant que les pneus de la voiture sont usés.
Avant d'entrer dans le détail de l'écriture des méthodes de la classe Voiture, voyons comment elles sont utilisées dans les différentes procédures de traitement des choix.
Voici le code de la procédure associée à ce choix:
def Choix_Nouvelle_Voiture () : global LaVoiture print( "---- CREATION D'UNE NOUVELLE VOITURE ------") im=input("Immatriculation : ") LaVoiture = Voiture() LaVoiture.Compteur=0 LaVoiture.Immat = im LaVoiture.AfficherAttributs()
La variable LaVoiture nous sert à mémoriser un objet de la classe Voiture. Comme nous souhaitons pouvoir y accéder depuis d'autres sous-programme, elle est déclarée en global. Les attributs de la nouvelle voiture sont créés et initialisés dans cette procédure, puis affichés par application de la méthode AfficherAttributs.
Voici le code de la procédure associée à ce choix:
def Choix_Rouler () : d=int(input("Distance : ")) LaVoiture.Rouler(d) LaVoiture.AfficherAttributs()
Remarquez que l'on suppose ici qu'une instance de voiture a été générée par le choix Nouvelle Voiture. Dans le cas contraire on obtiendrait une erreur d'exécution, car la variable LaVoiture ne serait pas définie.
def AfficherAttributs (self) : print("\n\tLa voiture : ",end="") print("Immatriculation: ",self.Immat,end="") print(", Kilometrage: ",self.Compteur)
Notez bien que le paramètre self représente l'objet auquel sera appliquée la méthode, c'est à dire celui qui figurera avant le point.
def ChangerPneu (self) : return (self.Compteur >= 10000)
Comme les sous-programmes, les méthodes sont divisées en deux catégories les fonctions et les procédures, selon qu'elles retournent un résultat ou qu'elles n'en retournent pas. ChangerPneu est une méthode de type fonction. Elle retourne un résultat booléen: True si la valeur du compteur est supérieure ou égale à 10000 et False sinon.
def Rouler (self, Km) : if not self.ChangerPneu() : self.Compteur = self.Compteur+Km else : print("Vos pneus sont uses !")