J'essaierai de traiter dans une série de tutorials les mécanismes des langages objet au fur et à mesure que je progresse dans leur compréhension.
la surcharge, les interfaces et l'utilisation du pattern adapter... pourraient être les suivants
Les classes abstraites.
Une classe abstraite, qu'est-ce que c'est? (reprise rapide de ce qu'on trouve partout)
C'est une classe où on laisse l'implémentation de certaines méthodes "vides" à ses descendantes.
Les méthodes à laisser "vides" doivent être specifiées abstract et ne pas avoir de corps {i.e.pas de {code} ). Par exemple:
public abstract void methode();
Du coup, la classe doit être precédée du mot clé abstract sinon le compilateur empêche la compilation..
public abstract class ClasseAbstraite {....code...}
Les classes abstraites ça sert quand?(on ne trouve pas toujours ça)
Je ne pense pas pouvoir être exhaustif sur les usages des classes abstraites car je suis relativement neuf en java, mais en tentant de concevoir un code "beau", on réfléchit à ce que rien ne soit écrit plusieurs fois (factorisation du code). Et la factorisation, la réutilisation du code, c'est la raison d'être de tous les mécanismes propres aux langages objet, notamment les classes abstraites.
** lorsque, dans une classe on veut appeler une méthode du niveau de conception des descendantes dans une methode appartenant au niveau de conception de la classe mère:(ouf ..)
exemple: On imagine que l'on souhaite coder une méthode commune à tous les animaux dans une classe animal : la methode sAlimenter. Sachant que tous les animaux vont obtenirNourriture, ingurgiter,digérer, on aimerait écrire :
class Animal{
....code...
public voidsAlimenter(){ //code du niveau de l'animal
//le tralala qu'on ne voudra pas recoder ailleurs si c'est du niveau de Animal
obtenirNourriture(); //à programmer au niveau de chaque descendant d'Animal
ingurgiter(); //à programmer au niveau de chaque descendant d'Animal
digérer(); //à programmer au niveau de chaque descendant d'Animal
}
}
Les methodes obtenirNourriture, ingurgiter, digérerdoivent être disponibles au niveau du code de l'animal, ce qui evitera ainsi de recoder pour chaque sorte d'animal la méthode sAlimenter. Or on ne peut pas décider d'une implémentation des trois methodes appelées dans sAlimenter pour que l'organisation du code corresponde au niveau de concept d l'animal. Mais les langages objets disposent de l'outil classe abstraite, qui permet de coder en fonction de methodes vides comme ici.
Il suffi de rajouter après le code précédent la signature des méthodes que l'on souhaite appeler sans en connaitre l'implementation (pour réserver un point d'entrée pour l'implémentation, lorsqu'elle sera disponible dans une instance de classe descendante):
public abstract void obtenirNourriture();
public abstract void ingurgiter();
public abstract void digérer();
Or pour que la compilation se fasse, il faut rajouter abstract devant la declaration de la classe
Au final le code complet de notre classe abstraite :
abstract class Animal{
....code...
public voidsAlimenter(){ //code du niveau de l'animal
//le tralala qu'on ne voudra pas recoder ailleurs si c'est du niveau de Animal
obtenirNourriture(); //à programmer au niveau de chaque descendant d'Animal
ingurgiter(); //à programmer au niveau de chaque descendant d'Animal
digérer(); //à programmer au niveau de chaque descendant d'Animal
}
public abstract void obtenirNourriture(); //points d'entrée pour le code des classes enfants
public abstract void ingurgiter();
public abstract void digérer();
}
Question à deux balles pour mieux comprendre:
oui mais pourquoi pas une simple classe avec des implementation "creuses" comme "public void obtenirNourriture() {};" et qui seraient surchargées par les classes filles?
Pourquoi pas mais :
1.Si on laisse à quelqu'un d'autre le soin de coder les classes filles, comment être certain que les méthodes seront implémentées? La classe abstraite est un moyen de s'en assurer, car le compilateur veillera pour nous.
2. Quand on appelera un objet de type Chien en tant qu'Animal (inventaire d'une menagerie par exemple), ce sont ces méthodes vides qui seront appelées, et pas celles des instances. Exemple :
Chien instanceDeChien;
Chat instanceDeChat;
Serpent instanceDeSerpent;
Animal[] menagerie=[instanceDeChien,instanceDeChat,instanceDeSerpent];
Animal[1].ingurgiter(); //ne fera rien si surcharge d'une méthode vide, mais ingurgitera à la maniere de Chat si dérivation d'une classe abstraite.
Voilà n'hésitez pas à rajouter des questions pour la rubrique Questions à deux balles, ou vos remarques critiques qui me permettront de ne pas laisser trainer trop d'erreurs.