đ§© Programmation objetâïž
1. đ Principesâïž
Comme son nom lâindique, le paradigme objet donne une vision du problĂšme Ă rĂ©soudre comme un ensemble dâobjets. Ces objets ont des caractĂ©ristiques et des comportements qui leurs sont propres, ce sont respectivement les attributs et les mĂ©thodes. Les objets interagissent entre eux avec des messages, en respectant leur interface (câest-Ă -dire lâensemble des spĂ©cifications en version compacte, les signatures des mĂ©thodes, on verra ce point plus en dĂ©tail tout au long de lâannĂ©e).
1.1 đ Un exemple « papier »âïž
Créons un jeu vidéo de type « hack and slash ». Dans ce type de jeu, le personnage joué doit tuer un maximum de monstres sur une carte de jeu. A lire le descriptif, 3 objets apparaissent naturellement :
- đ§ââïž Le personnage principal
- đč Les monstres
- đșïž La carte
On remarque immĂ©diatement que « monstre » aurait plutĂŽt tendance Ă dĂ©signer un type quâun objet unique : les objets sont tous typĂ©s. Le type dĂ©finit Ă la fois le nom de lâobjet, et ce quâil fait.
De mĂȘme, avec cette structure, on peut avoir plusieurs objets « personnages », pour jouer en multi-joueur, et bien sĂ»r plusieurs cartes.
1.2 đïž Classe et objetsâïž
Le « moule » avec lequel on va fabriquer un objet est appelé classe.
La classe personnage comprend par exemple les attributs :
- â€ïž Points de vie
- âïž DĂ©gĂąts maximums quâinflige le personnage
- đ Position
Elle comprend les méthodes :
- đ¶ DĂ©placement
- đĄïž Attaque
Et des mĂ©thodes qui permettent dâaccĂ©der aux attributs, ou bien de les modifier. Ce sont les accesseurs et les mutateurs. Les attributs sont cachĂ©s des objets extĂ©rieurs (le principe est lâencapsulation), ils sont privĂ©s. Les mĂ©thodes permettant dây accĂ©der sont Ă lâinverse publiques. Un objet extĂ©rieur ne doit pas pouvoir modifier Ă loisir les attributs dâun autre objet, en effet il doit y avoir un contrĂŽle de lâobjet sur ses propres attributs.
Quand on crĂ©e un personnage, lâordinateur crĂ©e une instance de la classe. Câest-Ă -dire que tous les objets de la classe auront les mĂȘmes attributs et mĂ©thodes, mais que deux objets de la mĂȘme classe peuvent avoir des valeurs diffĂ©rentes pour les attributs. Lâinstance est créée grĂące Ă un constructeur.
1.3 đĄ MĂ©taphoreâïž
- đ Une classe, câest le plan dâune maison (abstrait)
- đ Un objet, câest une maison issue du plan (concret). Ce quâil y a Ă lâintĂ©rieur dâune maison diffĂšre de lâintĂ©rieur dâune autre maison (dĂ©coration, mobilier, etcâŠ)
- đ Lâinterface câest le bouton qui permet de rĂ©gler le chauffage
- đ§ LâimplĂ©mentation (ou la rĂ©alisation) de lâinterface, câest la mĂ©thode de chauffage/climatisation retenue. Lâutilisateur ne connaĂźt pas le dĂ©tail de lâimplĂ©mentation, ce qui compte pour lui, câest le bouton de rĂ©glage (donc lâinterface)
2. Concepts de classe, attributs, mĂ©thodesâïž
2.1 â Une classe en Javaâïž
Le code suivant montre, Ă©tape par Ă©tape, la classe « personnage » telle quâon lâa dĂ©finie au paragraphe prĂ©cĂ©dent.
Le mot-clé pour définir une classe est class
. On donne ensuite les spécifications de la classe (on documente).
Une classe a une visibilité :
- đ public : le mot
class
est alors précédé depublic
, tout utilisateur qui importe le paquetage peut utiliser la classe. Dans ce cas elle doit ĂȘtre dĂ©finie dans un fichier qui a pour nom le nom de la classe. - đ privĂ© : le mot
class
est alors précédé deprivate
, seules des classes dĂ©finies dans le mĂȘme fichier peuvent utiliser cette classe. - đŠ paquetage : le mot
class
nâest pas prĂ©cĂ©dĂ© de mot particulier, toutes les classes du paquetage peuvent utiliser la classe.
public class Personnage {
"""
Personnage d'un jeu de type hack 'n slash
Attributs :
nom : chaine de caractĂšres, nom du personnage
pv : entier positif ou nul, points de vie du personnage
degats : entier strictement positif, dégats maximum du personnage
position : couple d'entiers donnant l'abscisse et l'ordonnée
du personnage sur la carte
Méthodes:
Init() constructeur de la classe Personnage
getAttribut() : accesseurs des attributs
setAttributs(nouvelle_valeur) : mutateurs des attributs.
Uniquement pour les attributs _pv et _position
deplacement(paramĂštres) : permet de changer la position
du personnage
attaque() : renvoie les dégùts faits à l'adversaire
"""
Personnage
est aussi passĂ© en argument le paramĂštre nom. Le constructeur initialise les attributs de lâobjet (points de vie, dĂ©gĂąts, position).
Tous les attributs sont prĂ©cĂ©dĂ©s dâun tiret bas « _
» pour signifier quâils sont privĂ©s.
Personnage(String nom) {
"""
Constructeur de la classe Personnage
Données:
nom : chaine de caractĂšres, nom du personnage
pv : entier positif ou nul, points de vie du personnage
degats : entier strictement positif, dégats maximum du personnage
position : couple d'entiers donnant l'abscisse et
l'ordonnée du personnage sur la carte
Résultat :
ne retourne rien, crée un nouveau Personnage
"""
nom = nom;
pv = 80;
degats = 8;
position = (0,0);
}
ou encore :
this.nom = nom;
Le mot-clé this désigne en permanence l'objet dans lequel on se trouve. Il existe dÚs l'instant que l'on se trouve dans l'instance de quelque chose. En particulier, il n'est pas défini dans un élément statique.
En gĂ©nĂ©ral, ce mot-clĂ© est utilisĂ© pour lever l'ambigĂŒitĂ© qui peut exister entre le champ d'une classe et un paramĂštre d'une mĂ©thode dans laquelle on se trouve, comme dans l'exemple qui suit.
âĄïž Exemple : Utilisation de this
pour lever l'ambiguïté entre un champ et un paramÚtre
2.2 đ Accesseurs (getters) et Mutateurs (setters)âïž
Les accesseurs nâont pas de paramĂštre, les mutateurs ont la nouvelle valeur. Il nây a pas forcĂ©ment de mutateurs (ni dâaccesseurs) pour tous les attributs : đ par exemple, le nom du personnage nâest pas modifiable ici.
On ne documente pas les accesseurs, on peut le faire pour les mutateurs.
đ„ Accesseurs des attributsâïž
public String getNom() {
return this.nom;
}
public int getPv() {
return this.pv;
}
public int getDegats() {
return this.degats;
}
public [] getPosition() {
return this.position;
}
đ€ Mutateurs des attributsâïž
public void setPv(int nouveaux_pv) {
"""
Les points de vie dâun personnage sont positifs ou nuls.
"""
if (nouveaux_pv < 0) {
pv = 0;
} else {
pv = nouveaux_pv;
}
}
public void setDegats(int nouveaux_degats) {
degats = nouveaux_degats;
}
2.3 đ ïž DĂ©finition dâune mĂ©thodeâïž
Une méthode est définie par :
- đ·ïž Son type de retour : type de la valeur retournĂ©e par la mĂ©thode.
Si la méthode ne retourne pas de valeur le type spécifié est alors
void
. Le type retournĂ© peut ĂȘtre un tableau. - đ Son nom
-
đą Ses paramĂštres :
-
spécifiés par leur type et leur nom
- séparés par des virgules
- tous transmis par valeur (mais la plupart sont des références)
On peut avoir un paramĂštre ellipse (...
) qui est en fait un tableau, et doit ĂȘtre le dernier paramĂštre.
Exempleâïž
void m(X ... e) {
// e est un tableau à une dimension d'éléments de type X
}
m
se fait alors de la façon suivante :
m(null);
m();
m(x1);
m(x1, x2);
âïž Signature dâune mĂ©thodeâïž
Une méthode est caractérisée par sa signature :
- đč son nom
- đč la liste des types des paramĂštres, dans l'ordre
đ Deux mĂ©thodes diffĂ©rentes ne peuvent pas avoir la mĂȘme signature. đ Deux mĂ©thodes ayant le mĂȘme nom mais des paramĂštres diffĂ©rents sont des surcharges.
đïž VisibilitĂ© dâune mĂ©thodeâïž
- đ public : accessible partout
- đ private : utilisable seulement dans la classe
- đĄïž protected : utilisable dans la classe et les classes dĂ©rivĂ©es
- đŠ paquetage : utilisable dans toutes les classes du mĂȘme paquetage
2.4 đ·ïž Attributsâïž
Un attribut se définit en donnant son type, puis son nom, ([]
pour un tableau), et éventuellement une partie initialisation.
đïž VisibilitĂ© dâun attributâïž
- đ public : sa dĂ©finition est prĂ©cĂ©dĂ©e de
public
, et il peut ĂȘtre utilisĂ© par tout utilisateur de la classe. - đ privĂ© : sa dĂ©finition est prĂ©cĂ©dĂ©e de
private
, et il ne peut ĂȘtre utilisĂ© quâĂ lâintĂ©rieur de la classe. - đĄïž protĂ©gĂ© : sa dĂ©finition est prĂ©cĂ©dĂ©e de
protected
, et il ne peut ĂȘtre utilisĂ© quâĂ lâintĂ©rieur de la classe, ou des classes dĂ©rivĂ©es. - đŠ paquetage : lâattribut peut ĂȘtre utilisĂ© dans toute classe du mĂȘme paquetage.
đ Ă lâintĂ©rieur de la dĂ©finition dâune mĂ©thode, lâaccĂšs Ă un attribut se fait soit directement, soit en prĂ©fixant l'attribut par this
qui est une rĂ©fĂ©rence Ă lâobjet pour lequel est appelĂ©e la mĂ©thode.
đ Ă lâextĂ©rieur de la dĂ©finition de la classe, lâaccĂšs se fait en Ă©crivant : đ nom de lâinstance . nom de lâattribut ou nom de lâinstance . nom de la mĂ©thode
Exemple
class Point {
private int x;
public int y;
void f() {
x = 0;
this.y = 1;
}
}
En dehors de la définition de la classe :
Point p = new Point();
p.x = 0; // â Erreur de compilation : la visibilitĂ© de x est privĂ©e !
p.y = 1; // â
đ Attributs publics, attributs privĂ©sâïž
En programmation objet, indĂ©pendamment du langage, on considĂšre que les attributs doivent ĂȘtre privĂ©s, encapsulĂ©s Ă lâintĂ©rieur de la classe et accessibles uniquement par mutateurs.
Vous trouverez sur le web de nombreux exemples de code rĂ©digĂ©s de cette maniĂšre, sans forcĂ©ment savoir si les propriĂ©tĂ©s avancĂ©es de Python ont Ă©tĂ© utilisĂ©es. Nous utiliserons Ă©galement ce type de code plus tard dans lâannĂ©e, pour simplifier lâĂ©criture des programmes.
â ïž Remarques
- â Ne pas donner le mĂȘme nom Ă une mĂ©thode et Ă un attribut dans une classe !
- â Plusieurs classes peuvent avoir les mĂȘmes noms de mĂ©thodes sans problĂšme.
đ En effet, lâappel dâune mĂ©thode passe par :
objet.méthode()
âĄïž La classe dĂ©finit son espace de noms.
3. đ CrĂ©ation dâinstancesâïž
Pour créer une instance de la classe A
, on écrira :
A a; // définition de la variable référence
a = new A(); // crĂ©ation de lâinstance
3.1 đ Ătapes de crĂ©ation avec new
âïž
La crĂ©ation dâune instance par lâopĂ©rateur new
se déroule en trois temps :
- đŠ RĂ©servation de lâespace mĂ©moire suffisamment grand pour reprĂ©senter lâobjet.
- ⥠Appel du constructeur de lâobjet â Initialisation des attributs et dâune rĂ©fĂ©rence Ă lâobjet reprĂ©sentant la classe de lâinstance en train dâĂȘtre créée.
- đ Renvoi dâune rĂ©fĂ©rence sur lâobjet nouvellement créé.
Exemple
class Point {
int x;
int y;
...
}
Point a, b;
a = new Point(...);
b = a;

3.2 đïž Destruction dâinstancesâïž
La destruction des instances se fait automatiquement par un thread, le garbage collector, qui cherche tous les objets qui ne sont plus référencés et les supprime.
đ Le garbage collector peut ĂȘtre appelĂ© directement par :
System.gc();
đ rĂ©sumĂ© POO
Concept | Idées Générales |
---|---|
đ Principes | |
Objets = attributs (caractĂ©ristiques) + mĂ©thodes (comportements), Encapsulation : attributs privĂ©s, accĂšs via getters/setters, Interface = ce quâon voit (contrat), ImplĂ©mentation = ce qui est fait en interne | |
đïž Classe et Objet | Classe = modĂšle / plan đ, Objet = instance concrĂšte đ , CrĂ©ation â via un constructeur, |
Destruction â via le Garbage Collector đïž | |
â Java (exemple) | Mot-clĂ© class , VisibilitĂ© : public /private /protected /package, MĂ©thodes â dĂ©finies par type retour + nom + paramĂštres, Signature = nom + liste des paramĂštres, Surcharge = mĂȘme nom, paramĂštres diffĂ©rents |
đŠ Attributs | Toujours privĂ©s (bonnes pratiques), AccĂšs uniquement via mutateurs (setters) |
4. đ§Ź HĂ©ritageâïž
LâhĂ©ritage permet de crĂ©er une nouvelle classe (dite classe fille) Ă partir dâune classe existante (dite classe mĂšre). La classe fille hĂ©rite :
- des attributs de la classe mĂšre
- des méthodes de la classe mÚre
Elle peut aussi :
- đ redĂ©finir (surcharger) certaines mĂ©thodes
- â ajouter ses propres attributs et mĂ©thodes
đ Cela favorise la rĂ©utilisation du code et lâorganisation hiĂ©rarchique des classes.
Exemple en Javaâïž
// Classe mĂšre
class Personnage {
protected String nom;
protected int pv;
public Personnage(String nom, int pv) {
this.nom = nom;
this.pv = pv;
}
public void afficher() {
System.out.println(nom + " possĂšde " + pv + " points de vie.");
}
}
// Classe fille
class Guerrier extends Personnage {
private int force;
public Guerrier(String nom, int pv, int force) {
super(nom, pv); // appel du constructeur de la classe mĂšre
this.force = force;
}
@Override
public void afficher() {
System.out.println(nom + " (Guerrier) possĂšde " + pv +
" points de vie et " + force + " de force.");
}
}
đ Remarquesâïž
super
appelle le constructeur ou une mĂ©thode de la classe mĂšre.- Les attributs hĂ©ritĂ©s peuvent ĂȘtre accessibles selon leur visibilitĂ© (
protected
oupublic
). - Une classe peut ĂȘtre dĂ©clarĂ©e
final
â empĂȘche lâhĂ©ritage.
5. đ Polymorphismeâïž
Le polymorphisme est la capacitĂ© dâun objet Ă prendre plusieurs formes. Dans le cadre de la POO :
- Plusieurs classes filles hĂ©ritant dâune mĂȘme classe mĂšre peuvent ĂȘtre manipulĂ©es comme si elles Ă©taient de la classe mĂšre.
- Les mĂ©thodes redĂ©finies sâexĂ©cutent en fonction de lâobjet rĂ©el.
đ Cela permet dâĂ©crire du code plus gĂ©nĂ©rique et rĂ©utilisable.
Exemple en Javaâïž
class Personnage {
protected String nom;
public Personnage(String nom) { this.nom = nom; }
public void attaquer() {
System.out.println(nom + " attaque avec ses poings.");
}
}
class Guerrier extends Personnage {
public Guerrier(String nom) { super(nom); }
@Override
public void attaquer() {
System.out.println(nom + " attaque avec une épée !");
}
}
class Mage extends Personnage {
public Mage(String nom) { super(nom); }
@Override
public void attaquer() {
System.out.println(nom + " lance un sort de feu !");
}
}
// Exemple d'utilisation
Personnage p1 = new Guerrier("Arthas");
Personnage p2 = new Mage("Merlin");
p1.attaquer(); // Arthas attaque avec une épée !
p2.attaquer(); // Merlin lance un sort de feu !
đ Remarquesâïž
- On peut manipuler une liste dâobjets de type
Personnage
et exécuterattaquer()
sans savoir si câest unGuerrier
ou unMage
. - Ce mĂ©canisme repose sur la liaison dynamique (mĂ©thode choisie Ă lâexĂ©cution).
-
On distingue :
-
Polymorphisme dâhĂ©ritage (comme ci-dessus)
- Polymorphisme dâinterface (implĂ©mentation de contrats communs).