Vocabulaire de la POO
I. Introductionâïž
Le paradigme objet
Il existe différentes maniÚres de voir la programmation, on parle de différents paradigmes de programmation. L'un d'eux est le paradigme objet. Lorsque l'on programme en utilisant ce paradigme on parle de programmation objet ou de programmation orientée objet (abrégé POO, ou OOP en anglais pour « Object-oriented programming »). Nous nous limiterons cette année à une introduction de la programmation objet.
Crédits
L'introduction qui suit est en trĂšs grande parti extraite du livre "Informatique" de la collection Fluoresciences de l'Ă©diteur Dunod
Auteurs : Delacroix, Joëlle; Barthélémy, François; Fournier-S'niehotta, Raphaël; Gil-Michalon, Isabelle; Lambert, Amélie; Plateau, AgnÚs; Rovedakis, Stéphane; Simonot, Marianne; Thion, Virginie; Waymel, Emmanuel. Informatique (Fluoresciences) (French Edition)
Les objets
La programmation orientĂ©e objet permet de structurer les logiciels en un assemblage dâentitĂ©s indĂ©pendantes qui interagissent. Ces entitĂ©s sont appelĂ©es des objets.
Prenons lâexemple dâun jeu de type tower defense. Il sâagit dâun jeu vidĂ©o dont lâobjectif est dâempĂȘcher des vagues dâennemis dâatteindre une certaine zone en plaçant sur le terrain des tours dĂ©fensives. Les tours tirent sur les ennemis Ă leur portĂ©e et se diffĂ©rencient les unes des autres selon des caractĂ©ristiques comme la portĂ©e de leur attaque, les dĂ©gĂąts causĂ©s etc. Chaque ennemi tuĂ© rapporte des points qui permettront dâacheter de nouvelles tours ou dâamĂ©liorer les tours existantes.
Nous aurons un objet terrain, des objets ennemis et des objets tours. Les trois points Ă retenir sur les objets sont les suivants :
1. Chaque objet possÚde ses propres caractéristiques : le coût, les dégùts causés, la portée pour les tours, la résistance, la rapidité, les points de vie pour les ennemis etc.
2. Les objets savent faire des choses. Câest ce que lâon appelle leur comportement : les ennemis savent se dĂ©placer, les tours savent attaquer.
3. Les objets ont des interactions, peuvent communiquer : les ennemis interagissent avec le terrain pour savoir vers oĂč ils peuvent aller, les tours interagissent avec les ennemis en les visant ou bien en leur infligeant des dĂ©gĂąts.
LâĂ©laboration dâun programme objet revient donc Ă trouver les objets permettant dâorganiser efficacement le programme et Ă dĂ©finir leurs interactions.
Cette façon de structurer les programmes en entités indépendantes qui interagissent offre de nombreux avantages :
- LâĂ©laboration du logiciel est facilement partageable entre plusieurs programmeurs.
- Un objet crĂ©Ă© pour un logiciel pourra facilement ĂȘtre rĂ©utilisĂ© dans un autre programme.
- Le logiciel sera plus facile Ă maintenir et Ă faire Ă©voluer. On pourra adapter le logiciel Ă de nouvelles exigences en modifiant uniquement le code des objets concernĂ©s par ce changement ou bien en ajoutant de nouveaux objets. Le reste du code nâaura pas besoin dâĂȘtre modifiĂ©.
Les classes
Un programme est constituĂ© dâobjets qui interagissent, mais certains objets relĂšvent dâune mĂȘme catĂ©gorie. Notre jeu vidĂ©o est constituĂ© de centaines dâobjets qui se rĂ©partissent dans trois catĂ©gories possibles : les tours, les terrains et les ennemis.
Relever dâune mĂȘme catĂ©gorie signifie quâil existe des caractĂ©ristiques et des comportements communs. Les caractĂ©ristiques des tours sont : les dĂ©gĂąts quâelles infligent, la portĂ©e de leurs armes, leur coĂ»t et leur capacitĂ© Ă attaquer. En programmation objet, les catĂ©gories sâappellent des classes.
Lâune des tours lance des flĂšches et lâautre des boules de feu. En programmation objet, on dĂ©finit des classes et on crĂ©e des objets, exemplaires de ces classes. Faisons une analogie avec un moulage : une fois le moule (la classe) fabriquĂ©, il sert Ă crĂ©er autant dâexemplaires similaires (les objets). Les objets sont des instances dâune classe.
Pour Ă©crire notre jeu en objet, nous aurions alors :
- à définir trois classes : Tour, Ennemi, Terrain,
- Ă coder lâinteraction avec lâutilisateur
- puis Ă crĂ©er des dizaines et des dizaines dâobjets tours, dâobjets ennemis et un terrain.
La dĂ©finition dâune classe permet dâintroduire de nouveaux types adaptĂ©s Ă notre application. Les variables pourront recevoir des valeurs de ces nouveaux types et, tout comme une variable qui contient un entier ne peut se voir appliquer que des opĂ©rations dĂ©finies sur les entiers, une variable contenant une valeur instance dâune classe ne pourra se voir appliquer que les comportements prĂ©vus dans la classe.
DĂ©finitions
En programmation orientĂ©e objet, un programme est un ensemble dâentitĂ©s qui interagissent. Ces entitĂ©s sont appelĂ©es des objets. Un objet possĂšde un Ă©tat (les donnĂ©es qui le caractĂ©rise) et des comportements (ce quâil sait faire).
Une classe permet de dĂ©finir une famille dâobjets. Ă partir dâune classe, on peut crĂ©er autant dâobjets que lâon veut. Ce sont des exemplaires, on dit en fait des instances de la classe.
Le mot clé class
âïž
Le mot clé class
Pour définir une classe en Python, on utilise le mot-clé class
. Câest une nouvelle instruction composĂ©e qui doit donc ĂȘtre suivie de « : ». Ă lâintĂ©rieur de la classe (câest-Ă -dire dans tout le texte indentĂ© qui suit lâentĂȘte avec le mot class), on dĂ©finit les caractĂ©ristiques et les comportements communs aux objets de la classe. Les caractĂ©ristiques sâappellent les attributs et les comportements sâappellent les mĂ©thodes.
Exemple
class Ennemi :
pass
Ă la place de pass
viendront les attributs et méthodes de cette classe.
Une dĂ©finition de classe est une instruction comme une autre en Python. On peut donc la mettre nâimporte oĂč. En pratique, on Ă©crit un module par classe et on importe le module. Par convention, le nom dâune classe commence par une majuscule.
CrĂ©er des objets Ă partir d'une classeâïž
Des objets Ă partir d'une classe
Une classe Ă©tant un moule, lâimportation dâune classe ne produit rien de concret sinon de donner la possibilitĂ© de crĂ©er des objets instances de cette classe, des ennemis concrets. Ceci se fait de la façon suivante :
Exemple
grosMechant = Ennemi()
unAutreEnnemi = Ennemi()
grosMechant
et unAutreEnnemi
sont deux ennemis concrets fabriquĂ©s Ă partir du mĂȘme moule.
Attributs et constructeursâïž
Exemple
Pour lâinstant, notre classe est une coquille vide. Il faut maintenant y ajouter les caractĂ©ristiques communes aux ennemis. Dans notre version simplifiĂ©e, les caractĂ©ristiques seront les suivantes :
- leur position sur le terrain repérée par une position en X et une position en Y ;
- leurs points de vie ;
- leur rapidité ;
Vocabulaire
En terminologie objet, il faut dĂ©finir dans la classe Ennemi quatre attributs ou variables dâinstances. Ceci se fait de la façon suivante :
Exemple
class Ennemi :
def __init__(self) :
self.posX = 0
self.posY = 0
self.pv = 100
self.rapidite = 2
__init__
Nous avons déjà rencontré le mot clé def
pour dĂ©finir des fonctions. Une classe est constituĂ©e essentiellement dâune suite de dĂ©finitions de fonctions qui reprĂ©sentent les fonctions que lâon va pouvoir utiliser sur les objets instances de la classe. Les fonctions internes aux classes sâappellent des mĂ©thodes.
La méthode __init__
est une mĂ©thode particuliĂšre quâon appelle le constructeur de la classe. Cette mĂ©thode est utilisĂ©e lors de la crĂ©ation des objets. Son paramĂštre self reprĂ©sente lâobjet qui va ĂȘtre crĂ©e.
Attention, il y a deux tirets underscore avant et aprĂšs le mot init
.
Attributs
Le corps de __init__
indique quâĂ chaque fois que lâon crĂ©e un objet ennemi, il faut lui associer quatre variables qui lui sont propres, nommĂ©es posX, posY, pv
et rapidite
et les initialiser avec les valeurs respectives 0, 0, 100 et 2. Tous les ennemis possĂšderont ces quatre variables. Ces variables sâappellent les attributs ou les variables dâinstance de la classe. Ce sont bien des caractĂ©ristiques communes aux ennemis. Mais ils possĂšdent chacun leur propre copie de ces variables : leurs valeurs pourront donc Ă©voluer de façon indĂ©pendante.
AccĂ©der aux attributs des objets d'une classeâïž
Exemple
Nos deux objets grosMechant
et unAutreEnnemi
naissent avec les mĂȘmes caractĂ©ristiques et les mĂȘmes valeurs pour ces caractĂ©ristiques. Nous pouvons accĂ©der aux valeurs de ces attributs pour chacun dâentre eux au moyen de la notation pointĂ©e.
grosMechant = Ennemi()
unAutreEnnemi = Ennemi()
grosMechant.posX
Testons
Exécuter le script ci-dessous :
Dans la console située en dessous du script, recopier et exécuter ligne par ligne à la main (sans copier/coller) :
>>> grosMechant.posX
>>> grosMechant.pv
>>> unAutreEnnemi.pv
>>> grosMechant.pv = 50
>>> grosMechant.pv
>>> unAutreEnnemi.pv
Résumé
grosMechant.pv
dĂ©signe lâattribut pv
de grosMechant
, unAutreEnnemi.pv
dĂ©signe lâattribut pv
de unAutreEnnemi
. On peut modifier la valeur des points de vie de grosMechant
cela nâaffecte en rien les points de vie de unAutreEnnemi
. Les objets dâune mĂȘme classe ont donc les mĂȘmes attributs. Les valeurs de ces attributs sont propres Ă chaque objet et Ă©voluent de façon indĂ©pendante au fil de lâexĂ©cution du programme : on peut tout Ă fait imaginer que les points de vie de grosMechant
tombent Ă 0 au bout de trois tours alors quâunAutreEnnemi
survit jusquâau bout.
Des constructeurs plus souplesâïž
Des paramĂštres
-
Avec le constructeur que nous avons Ă©crit, tous les objets de la classe
Ennemi
sont initialisĂ©s Ă la crĂ©ation avec les mĂȘmes valeurs. Ceci nâest pas trĂšs pratique. Nous aimerions pouvoir crĂ©er un vrai gros mĂ©chant trĂšs lent mais avec plein de points de vie et un ennemi moins costaud mais beaucoup plus rapide. En dâautres termes, nous aimerions pouvoir choisir les valeurs des attributsrapidite
etpv
au moment de la crĂ©ation (instanciation) dâun objet. -
Comme
__init__
est une mĂ©thode comme une autre, il suffit de lui ajouter des paramĂštres permettant de transmettre les valeurs que lâon souhaite pour les attributs dont lâinitialisation doit varier. Dans notre cas, nous allons ajouter deux paramĂštresr
etp
pour fixer la valeur de ces deux attributs. Il suffira alors dâinitialiserself.rapidite
avec lâune etself.pv
avec lâautre. Nous nâajoutons pas de paramĂštres permettant de transmettre une valeur pourposX
etposY
car nous voulons que tous les ennemis partent du mĂȘme endroit.
Testons
Nous avons maintenant le droit de transmettre deux valeurs lorsque nous créons des objets Ennemi.
Exécuter le script ci-dessous :
# Tests
(insensible Ă la casse)(Ctrl+I)
(Ctrl+Clic pour inverser les colonnes)
Dans la console située en dessous du script, recopier et exécuter ligne par ligne à la main (sans copier/coller) :
>>> LePetitRapide.pv
>>> LePetitRapide.rapidite
>>> LeVraiGrosMechant.pv
>>> LeVraiGrosMechant.rapidite
>>> LeVraiGrosMechant.posX
>>> LePetitRapide.posX
đ CrĂ©ez votre propre instance de la classe Ennemi_2
, et faites afficher ses attributs comme ci-dessus.
Les mĂ©thodesâïž
Les méthodes
Nous avons dit en introduction que dĂ©finir une classe câest dĂ©finir des attributs et les comportements communs aux objets de la classe. Nous savons maintenant dĂ©finir les attributs. Quâen est-il des comportements ?
Les comportements reprĂ©sentent ce que les objets savent faire. Dans notre version, nous voulons doter les ennemis de capacitĂ©s trĂšs rudimentaires : se dĂ©placer vers un nouveau point, recevoir des points de dĂ©gĂąts et afficher leurs caractĂ©ristiques. Pour dĂ©finir un comportement, il suffit dâajouter une mĂ©thode Ă notre classe. Ces mĂ©thodes auront toujours self
comme premier paramĂštre de façon Ă dĂ©signer lâobjet sur lequel va sâappliquer la mĂ©thode. Lors de lâappel de la mĂ©thode, la notation pointĂ©e nous permettra de dĂ©signer lâobjet qui prendra la place de self
.
La méthode recevoirDegats
Un ennemi doit pouvoir subir un certain nombre de dégùts. Nous ajoutons donc une méthode recoitDegats
dans la classe Ennemi
. Cette méthode possÚde deux paramÚtres : self
, qui dĂ©signe lâobjet ennemi qui subit les dĂ©gĂąts et deg
, le nombre de points de dĂ©gĂąts quâil doit recevoir. Lorsquâun ennemi reçoit des points de dĂ©gĂąts, cela doit modifier ses points de vie. Puisque self
dĂ©signe lâobjet sur lequel on applique la mĂ©thode, self.pv
désigne son attribut personnel pv
. Il suffit donc dâenlever la valeur de deg
Ă cet attribut.
Exécuter le script ci-dessous :
# Tests
(insensible Ă la casse)(Ctrl+I)
(Ctrl+Clic pour inverser les colonnes)
đ Jouez un peu avec la mĂ©thode recoitDegats
MĂ©thode
Une méthode se définit donc exactement comme une fonction à la seule différence que son premier paramÚtre est toujours self
qui dĂ©signe lâobjet sur lequel sâappliquera la mĂ©thode. Par voie de consĂ©quence, le corps de la mĂ©thode peut faire rĂ©fĂ©rence Ă self
.
Remarque
đ” La mĂ©thode recoitDegats recoit 2 arguments : self et deg.
Mais dans l'appel on Ă©crit : mechant.recoitDegats(25)
Donc un seul paramĂštre !!!
self
est l'objet lui mĂȘme, ici nommĂ© mechant
.
Les méthodes seDeplace et affiche
Un ennemi doit pouvoir se déplacer vers une nouvelle position. Nous ajoutons donc une méthode seDeplace
dans la classe Ennemi_4
. Cette méthode possÚde trois paramÚtres : self
et deux entiers représentant les coordonnées de la nouvelle la nouvelle position. Cela doit modifier les attributs posX
et posY
. Pour afficher, on se contente dâafficher les valeurs de tous les attributs de lâobjet. Seul self
est en paramĂštre.
# Tests
(insensible Ă la casse)(Ctrl+I)
(Ctrl+Clic pour inverser les colonnes)
-
Maintenant que notre classe est enrichie de trois comportements, nous pouvons les utiliser sur des objets instances de la classe
Ennemi_4
. -
Pour faire se dĂ©placer grosMechant au point dâabscisse 5 et dâordonnĂ©e 8, il suffit dâĂ©crire
grosMechant.seDeplace( 5,8)
. Le corps de la mĂ©thode va ĂȘtre exĂ©cutĂ© dans un contexte oĂčself
désigneragrosMechant
,nouveauX
désignera 5 etnouveauY
désignera 8 et modifiera uniquement les attributsposX
etposY
degrosMechant
. - Soulignons le fait que si
self
doit toujours ĂȘtre le premier paramĂštre dâune mĂ©thode, il nâest pas prĂ©sent entre les parenthĂšses lors de lâappel de la mĂ©thode. Si une mĂ©thode dans une classe C est de la formenomMethode( self, par1,.., parn
) alors on lâutilise de la façon suivante :unObjet.uneMethode( val1,... valn)
. - Le corps de la méthode sera alors exécuté avec
unObjet
Ă la place deself
,val1
Ă la place depar1
, âŠetvaln
Ă la place deparn
.
Dans la console située en dessous du script, recopier et exécuter ligne par ligne à la main (sans copier/coller) :
>>> grosMechant = Ennemi_4(100, 2)
>>> unAutreEnnemi = Ennemi_4(50, 4)
>>> grosMechant.affiche()
>>> unAutreEnnemi.affiche()
>>> grosMechant.seDeplace(5, 8)
>>> grosMechant.affiche()
>>> unAutreEnnemi.affiche()
>>> grosMechant.recoitDegats(50)
>>> unAutreEnnemi.recoitDegats(10)
>>> grosMechant.affiche()
>>> unAutreEnnemi.affiche()
MĂ©thode et classe
đ Les mĂ©thodes dĂ©finies dans une classe ne sont applicables que sur les objets instances de la classe. Inversement, un objet instance dâune classe ne peut se voir appliquer que les mĂ©thodes de cette classe.
Tester
# Tests
(insensible Ă la casse)(Ctrl+I)
(Ctrl+Clic pour inverser les colonnes)
# Tests
(insensible Ă la casse)(Ctrl+I)
(Ctrl+Clic pour inverser les colonnes)
Solution
Dans ces exemples, a
contient une valeur de type int
mais pas de valeur de type Ennemi_4
. Les méthodes de Ennemi_4
ne lui sont donc pas applicables. De la mĂȘme façon, grosMechant
contient une valeur de type Ennemi_4
et + nâest pas dĂ©finie sur les valeurs de ce type.
Les mĂ©thodes peuvent renvoyer un rĂ©sultatâïž
Les méthodes peuvent renvoyer un résultat
Les mĂ©thodes ont le plus souvent pour rĂŽle de modifier lâĂ©tat de lâobjet sur lequel elles sâappliquent. Elles peuvent aussi, comme les fonctions, renvoyer un rĂ©sultat. Par exemple, dans notre classe, nous pouvons dĂ©finir une mĂ©thode estVivant
qui teste si lâennemi sur lequel elle sâapplique a encore des points de vie.
Testons
Exécuter le script ci-dessous :
# Tests
(insensible Ă la casse)(Ctrl+I)
(Ctrl+Clic pour inverser les colonnes)
Dans la console située en dessous du script, recopier et exécuter ligne par ligne à la main (sans copier/coller) :
>>> grosMechant.estVivant()
Des mĂ©thodes spĂ©cialesâïž
La méthode spéciale __str__()
Nous connaissons la méthode print()
pour les valeurs de type simple. Cette mĂ©thode est aussi applicable sur des objets. Par dĂ©faut, elle affiche des informations inexploitables. Vous pouvez choisir ce quâelle affiche pour les classes que vous dĂ©finissez en ajoutant dans ces classes la mĂ©thode __str__()
. La méthode __str__()
doit renvoyer une chaĂźne de caractĂšres. print()
utilisera cette chaĂźne de caractĂšres pour faire lâaffichage. Ceci est beaucoup plus souple que de dĂ©finir des mĂ©thodes afficher()
. Pour la classe Ennemi
, on remplacerait la méthode affiche()
par la méthode __str__()
définie ainsi :
Testons
Exécuter le script ci-dessous :
# Tests
(insensible Ă la casse)(Ctrl+I)
(Ctrl+Clic pour inverser les colonnes)
đ Nous pouvons Ă prĂ©sent afficher un ennemi en utilisant print()
.
đ Faites vos propres essais ...
Objets et rĂ©fĂ©rencesâïž
Objets et références
Lorsque nous lions une variable Ă un objet, la variable ne contient pas lâobjet lui- mĂȘme, mais une rĂ©fĂ©rence Ă lâobjet, câest-Ă -dire lâadresse mĂ©moire oĂč se situe lâobjet. DĂšs lors, deux variables peuvent rĂ©fĂ©rencer le mĂȘme objet. Ce sont alors deux moyens dâaccĂšs au mĂȘme objet. On peut donc modifier lâobjet par lâintermĂ©diaire de lâune des variables comme de lâautre. Cette possibilitĂ© ouvre la voie Ă de nombreuses erreurs de programmation. Il faut donc ĂȘtre capable de faire la diffĂ©rence entre deux variables rĂ©fĂ©rençant des objets ayant la mĂȘme valeur et deux variables qui rĂ©fĂ©rencent le mĂȘme objet.
Testons
Exécuter le script ci-dessous :
# Tests
(insensible Ă la casse)(Ctrl+I)
(Ctrl+Clic pour inverser les colonnes)
Dans la console située en dessous du script, recopier et exécuter ligne par ligne à la main (sans copier/coller) :
>>> x
>>> y
>>> z
Objets et références
La valeur de la variable x est donnée par Ennemi_6( 10,20)
. Ceci crée un nouvel objet ennemi en mémoire et x
reçoit comme valeur lâadresse de ce nouvel objet qui nous est indiquĂ©e.
Il en est de mĂȘme pour y
: il y a crĂ©ation dâun nouvel objet stockĂ© dans une adresse mĂ©moire diffĂ©rente et y reçoit cette adresse comme valeur. En revanche,
z = y
donne Ă z
la valeur de y
Ă savoir lâadresse de y
Les variables x
et y
, bien quâĂ©tant liĂ©es Ă des objets ayant les mĂȘmes valeurs, sont indĂ©pendantes : la modification de lâune nâa aucun impact sur lâautre. Ce nâest pas la mĂȘme chose pour y
et z
comme lâindique lâexemple suivant :
Testons
Exécuter le script ci-dessous :
# Tests
(insensible Ă la casse)(Ctrl+I)
(Ctrl+Clic pour inverser les colonnes)
Objets et références
Le fait dâavoir modifiĂ© les points de vie de y a aussi modifiĂ© ceux de z.
đ” Cette notion est rendue confuse du fait de lâabus de langage que nous faisons : nous ne devrions pas dire que nous modifions les points de vie de y
mais que nous modifions les points de vie de lâobjet rĂ©fĂ©rencĂ© par y.
CrĂ©er des clonesâïž
Objets et références
đ Le fait que deux variables puissent partager le mĂȘme objet doit ĂȘtre utilisĂ© Ă bon escient. Prenons lâexemple dâun jeu contenant des monstres qui ont un pouvoir de clonage. La classe suivante reprĂ©sente ces monstres et contient deux versions possibles de la mĂ©thode permettant de crĂ©er un clone.
Testons
Exécuter le script ci-dessous :
# Tests
(insensible Ă la casse)(Ctrl+I)
(Ctrl+Clic pour inverser les colonnes)
Résumé
Dans notre exemple, mic
a reçu huit points de dégùts et a donc vingt-deux points de vie, alors que clone1
qui a été créé par copie de mic
au moment oĂč celui-ci avait vingt-cinq points de vie a reçu vingt-cinq points de dĂ©gĂąts et est donc mort.
La méthode seClonerV2()
est tout Ă fait diffĂ©rente. Au lieu de crĂ©er un nouveau monstre ayant les mĂȘmes valeurs que celles du monstre original, elle renvoie self
, câest-Ă -dire une rĂ©fĂ©rence au monstre original. Toute attaque sur le monstre affaiblira son clone et inversement.
Ici, clone2
se retrouve avec sept points de vie : il est affectĂ© par les dĂ©gĂąts quâil reçoit (15) mais aussi par ceux que moc
reçoit (3). Il en est de mĂȘme pour moc
. Clairement, pour crĂ©er un clone, câest la premiĂšre version quâil faut choisir.
Remarque
đą Nous laissons au lecteur le soin dâimaginer le temps que lâon peut mettre Ă repĂ©rer lâerreur lorsque lâon a Ă©crit la seconde version sans en connaĂźtre les consĂ©quences...
đ Ce qu'il faut retenirâïž
Ă savoir đ
-
Une classe permet de dĂ©finir un ensemble dâobjets qui ont des caractĂ©ristiques communes. Câest un moule permettant de crĂ©er une infinitĂ© dâobjets diffĂ©rents dans leurs valeurs mais similaires dans leur structure. Ces objets sont les instances de la classe
-
DĂ©finir une classe câest dĂ©finir lâensemble des attributs et des mĂ©thodes caractĂ©risant tous les objets instances de la classe.
-
Les attributs sont en gĂ©nĂ©ral dĂ©clarĂ©s privĂ©s afin dâen interdire lâaccĂšs Ă lâextĂ©rieur de la classe. Câest ce quâon appelle lâencapsulation.
-
La méthode
__init__
est le constructeur de la classe. Elle est utilisĂ©e Ă la crĂ©ation des objets de la classe et initialise les valeurs des attributs de lâobjet. -
Pour utiliser une méthode
m(self, âŠ)
dâune classeC
, il faut avoir un objetmon_objet
instance de la classeC
et faire :mon_objet.m(...)
II. Vocabulaire de la programmation objetâïž
Les objets
La programmation objet consiste Ă regrouper donnĂ©es et traitements dans une mĂȘme structure appelĂ©e objet. Elle possĂšde l'avantage de localiser en un mĂȘme endroit toute l'implĂ©mentation d'une structure de donnĂ©es abstraite.
Prenons une voiture comme exemple
Une voiture peut ĂȘtre considĂ©rer comme un objet.
-
On peut lui associer des informations comme sa couleur, sa marque et sa catégorie : il s'agit des attributs de notre objet.
-
On peut également définir des mécanismes concernant cet objet comme démarrer, accélérer, freiner, klaxonner : il s'agit des méthodes qui vont s'appliquer sur notre objet.
Les objets
ConcrÚtement, un objet est une structure de données abstraite regroupant :
- des données associées à cet l'objet que l'on appelle des attributs.
- des fonctions (ou procédures) s'appliquant sur l'objet que l'on appelle des méthodes.
Exemple de classe
Reprenons l'exemple de la voiture
Ses attributs ( couleur, marque, ...) et méthodes ( démarrer, accélerer, ...) sont réunis dans ce qu'on appelle une classe qui est donc un modÚle (moule) décrivant un objet, ici la voiture. On va donc définir une classe Voiture
qui va ĂȘtre le moule (modĂšle) pour la fabrication de tous les objets voitures
. On peut la schématiser ainsi :
classDiagram
class Voiture{
String Couleur
String Marque
String Catégorie
DĂ©marrer()
Accélérer()
Freiner()
Klaxonner()
}
Les objets sont ensuite créés à partir de ce moule. On peut fabriquer deux objets clio
et c3
, qui sont deux instances de la classe Voiture
en Ă©crivant simplement les deux instructions suivantes :
clio = Voiture()
c3 = Voiture()
Les instances
On va donc pouvoir créer facilement des objets Voiture
grĂące Ă cette classe (moule).
Il suffit pour les construire d'utiliser le nom de la classe (qui est aussi le nom du constructeur d'objets de cette classe). Chaque objet ainsi créé est une instance de la classe.
Remarque
- Les méthodes définies dans une classe ne sont applicables que sur les objets instances de la classe.
- Inversement, un objet instance dâune classe ne peut se voir appliquer que les mĂ©thodes de cette classe.
AccÚs aux attributs et aux méthodes
Pour accéder aux attributs et aux méthodes d'une classe on utilise la notation pointée.
Dans notre exemple :
clio.marque
donne la marque de l'objet clio, c'est Ă dire Renaultclio.klaxonner()
va faire klaxonner notre voiture (virtuelle). Nous reviendrons sur cela un peu plus loin.
III. Classes et objets en Pythonâïž
En Python, tout est objet !
Vous ne le saviez sans doute pas, mais les objets vous connaissez déjà (et oui !)
Les listes en Python
Les listes sont un type abstrait list
dans python; et vous utilisez la notation pointée pour ajouter un élément.
Recopier une par une les lignes suivantes, et les exécuter une par une.
>>> ma_liste = [2, 3, 5]
>>> type(ma_liste)
>>> ma_liste.append(8)
>>> ma_liste
Les types en Python
L'affichage montre que tous les types en Python sont des classes. Les entiers sont des objets de la classe int
, les flottants sont des objets de la classe float
, etc. Pour créer un entier ou une liste il suffit de les construire en utilisant le nom de leurs classes respectives
Recopier une par une les lignes suivantes, et les exécuter une par une.
>>> type(int)
>>> type(float)
>>> entier = int()
>>> type(entier)
>>> ma_liste = list()
>>> type(ma_liste)
Interface d'une classe
En définissant une classe on définit un type abstrait de données. Comme tout type abstrait, une classe possÚde donc une interface qui décrit l'ensemble des méthodes auxquelles on a accÚs pour manipuler les objets de cette classe.
On peut utiliser la fonction dir
pour lister tous les attributs et méthodes d'un objet.
Taper dir(list)
dans la console python pour visualiser les différentes méthodes et attributs de list
.
Les méthodes du type prédéfini list
On retrouve ici les méthodes applicables sur les objets du type prédéfini list
.
Son interface est disponible dans la documentation officielle
Vous noterez que l'interface ne précise pas la façon dont les méthodes sont implémentées mais juste la façon de les utiliser, ce qui suffit largement généralement.
On constate aussi qu'il y a de nombreuses méthodes dont le nom est encadré d'un double underscore __
.
Ce sont des méthodes spéciales . Nous reviendrons sur quelques-unes d'entre elles un peu plus tard.
# Tests
(insensible Ă la casse)(Ctrl+I)
(Ctrl+Clic pour inverser les colonnes)