25.04.2001 - version 1.4 [Armel] - Mise en forme du code html (titres-hx[verdan
25.04.2001 - version 1.4 [Armel] - Mise en forme du code html (titres-hx[verdana], paragraphes-p[Georgia], code-blockquote 13.04.2001 - version 1.3 [Florence DEFAIX] - Après corrections proposées par Jérome QUELIN et J-P VIDAL. 4: Initialisation & Nettoyage Depuis le début de la révolution informatique, la programmation «sans garde-fou» est la principale cause des coûts de développement excessifs. L'initialisation et la libération d'éléments sont deux problèmes majeurs. De nombreux bogues en C surviennent lorsque le programmeur oublie d'initialiser une variable. L'utilisation de blibliothèques augmente ce risque car les utilisateurs ne savent pas toujours comment initialiser certains composants, ni même qu'ils le doivent. La phase de nettoyage ou libération pose problème dans la mesure où il est très facile d'oublier l'existence d'un élément dont on n'a plus besoin, car justement il ne nous intéresse plus. Dans ce cas, certaines ressources utilisées par un élément oublié sont conservées. Ce phénomène peut entraîner un manque de ressources (dans la majorité des cas, un manque de mémoire). C++ a introduit la notion de constructeur, une méthode appelée automatiquement à la création d'un objet. Java utilise aussi les constructeurs, associé à un ramasse-miettes qui libère les ressources mémoire lorsqu'elles ne sont plus utilisées. Ce chapitre décrit les concepts d'initialisation et de libération, ainsi que leur support dans Java. Garantie d'initialisation grâce au constructeur Pour chaque classe il serait possible de créer une méthode initialise( ). Ce nom inciterait à exécuter la méthode avant d'utiliser l'objet. Malheureusement ce serait à l'utilisateur de se souvenir d'appeler cette méthode pour chaque instance. En Java, le concepteur d'une classe peut garantir son initialisation grâce à une méthode spéciale que l'on dénomme constructeur. Quand une classe possède un constructeur, Java l'appelle automatiquement à toute création d'objets, avant qu'ils ne puissent être utilisés. L'initialisation est donc bien garantie. Le premier problème consiste à trouver un nom pour cette méthode ce qui entraîne deux nouveaux problèmes. Tout d'abord il pourrait y avoir un conflit avec le nom d'un attribut. Ensuite c'est à la compilation que l'appel du constructeur est vérifié. Il faut donc que le compilateur puisse décider du nom du constructeur. La solution de C++ paraît la plus simple et la plus logique, elle est donc aussi utilisée en Java. Il faut donc donner au constructeur le nom de sa classe. Il semble naturel qu'une telle méthode soit en charge de l'initialisation de la classe. Voici une classe avec un constructeur : //: c04:SimpleConstrutor.java // Démonstration d'un constructeur. class Rock { 1 of 46 7/6/01 9:45 AM 4: Initialization & Cleanup file:///D|/Daniel/TIJ2FR/All/Chapter04.htm Rock() { // Ceci est un constructeur System.out.println("Creating Rock"); } } public class SimpleConstructor { public static void main(String[] args) { for(int i = 0; i < 10; i++) new Rock(); } } ///:~ Quand un objet est créé : new Rock(); de l'espace mémoire est alloué et le constructeur est appelé. L'objet sera obligatoirement initialisé avant qu'il ne puisse être manipulé. Notez que la convention de nommage qui impose une minuscule pour la première lettre des noms de méthode ne s'applique pas aux constructeurs, leur nom devant exactement coïncider avec celui de la classe. Comme les autres méthodes, un constructeur peut prendre des paramètres. Cela permet de préciser comment l'objet va être créé. Notre premier exemple peut facilement être modifié pour que le constructeur prenne un unique paramètre : //: c04:SimpleConstructor2.java // Les constructeurs peuvent prendre des paramètres. class Rock2 { Rock2(int i) { System.out.println( "Creating Rock number " + i); } } public class SimpleConstructor2 { public static void main(String[] args) { 2 of 46 7/6/01 9:45 AM 4: Initialization & Cleanup file:///D|/Daniel/TIJ2FR/All/Chapter04.htm for(int i = 0; i < 10; i++) new Rock2(i); } } ///:~ Les paramètres des constructeurs permettent de personnaliser la création des objets. Par exemple, si la classe Tree (arbre) a un constructeur avec un paramètre de type int qui détermine la hauteur de l'arbre, un objet Tree se crée de la façon suivante : Tree t = new Tree(12); // arbre de 12 pieds De plus, si Tree(int) est le seul constructeur, le compilateur ne permettra pas de créer un objet Tree d'une autre façon. La notion de constructeur élimine toute une catégorie d'erreurs et rend plus aisée la lecture du code. Dans le fragment de code précédent, par exemple, il n'y a pas d'appel explicite à une certaine méthode initialise( ) qui serait conceptuellement séparée de la définition. En Java, definition et initialisation sont des concepts unifiés - il est impossible d'avoir l'un sans l'autre. Un constructeur est une méthode très spéciale de par le fait qu'elle n'a pas de valeur de retour. Cela n'a absolument rien à voir avec le type de retour void, qui signifie qu'une méthode ne renvoie rien mais qu'il aurait tout à fait été possible de lui faire renvoyer autre chose. Les constructeurs ne retournent rien et on n'a pas le choix. S'il y avait une valeur de retour, et si l'on pouvait choisir son type, le compilateur devrait trouver une utilisation à cette valeur. Surcharge de méthodes L'un des points les plus importants de tout langage de programmation est le nommage. Créer un objet revient à donner un nom à un emplacement mémoire. Une méthode est un nom d'action. En utilisant des noms pour décrire un système, on simplifie la lecture et la modification des programmes. Cela s'apparente à l'écriture en prose dont le but est de communiquer avec le lecteur. On se réfère à tous les objets et méthodes en utilisant leurs noms. Des noms biens choisis rendent la compréhension du code plus aisée, tant pour le développeur que pour les relecteurs. Les difficultés commencent lorsque l'on essaie d'exprimer les nuances subtiles du langage humain dans un langage de programmation. Très souvent, un même mot a plusieurs sens, on parle de surcharge. Cette notion est très pratique pour exprimer les différences triviales de sens. On dit « laver la chemise » , « laver la voiture » et « laver le chien » . Cela paraîtrait absurde d'être obligé de dire « laverChemise la chemise » , « laverVoiture la voiture » et « laverChien le chien » pour que l'auditoire puisse faire la distinction entre ces actions. La plupart des langages humains sont redondants à tel point que même sans entendre tous les mots, il est toujours possible de comprendre le sens d'une phrase. Nous n'avons aucunement besoin d'identifiants uniques, le sens peut être déduit du contexte. La plupart des langages de programation (C en particulier) imposent un nom unique pour chaque fonction. Ils ne permettent pas d'appeler une fonction affiche( ) pour afficher des entiers et une autre appelée affiche( ) pour afficher des flottants, chaque fonction doit avoir un nom unique. 3 of 46 7/6/01 9:45 AM 4: Initialization & Cleanup file:///D|/Daniel/TIJ2FR/All/Chapter04.htm En Java (et en C++), un autre facteur impose la surcharge de noms de méthodes : les constructeurs. Comme le nom d'un constructeur est déterminé par le nom de la classe, il ne peut y avoir qu'un seul nom de constructeur. Mais que se passe-t-il quand on veut créer un objet de différentes façons ? Par exemple, supposons que l'on construise une classe qui peut s'initialiser de façon standard ou en lisant des informations depuis un fichier. Nous avons alors besoin de deux constructeurs, l'un ne prenant pas de paramètre ( le constructeur par défaut, aussi appelé le constructeur sans paramètre / no-arg ), et un autre prenant une Chaîne / String comme paramètre, qui représente le nom du fichier depuis lequel on souhaite initialiser l'objet. Tous les deux sont des constructeurs, ils doivent donc avoir le même nom, le nom de la classe. Cela montre que la surcharge de méthode est essentielle pour utiliser le même nom de méthode pour des utilisations sur différents types de paramètres. Et si la surcharge de méthode est obligatoire pour les constructeurs, elle est aussi très pratique pour les méthodes ordinaires. L'exemple suivant montre à la fois une surcharge de constructeur et une surcharge de méthode ordinaire : //: c04:Overloading.java // Exemple de surcharge de constructeur // et de méthode ordinaire. import java.util.*; class Tree { int height; Tree() { prt("Planting a seedling"); // Planter une jeune pousse height = 0; } Tree(int i) { prt("Creating new Tree that is " // Création d'un Arbre + i + " feet tall"); // de i pieds de haut height = i; } void info() { prt("Tree is " + height // L'arbre mesure x pieds + " feet tall"); } void info(String s) { prt(s + ": Tree is " // valeur de s : L'arbre mesure x pieds + height + " feet tall"); } 4 of 46 7/6/01 9:45 AM 4: Initialization & Cleanup file:///D|/Daniel/TIJ2FR/All/Chapter04.htm static void prt(String s) { System.out.println(s); } } public class Overloading { public static void main(String[] args) { for(int i = 0; i < 5; i++) { Tree t = new Tree(i); t.info(); t.info("overloaded method"); } // constructeur surchargé : new Tree(); } } ///:~ Un objet Tree peut être créé soit en tant que jeune pousse, sans fournir uploads/Litterature/ chapter-04.pdf
Documents similaires










-
31
-
0
-
0
Licence et utilisation
Gratuit pour un usage personnel Attribution requise- Détails
- Publié le Oct 24, 2021
- Catégorie Literature / Litté...
- Langue French
- Taille du fichier 0.0969MB