Département d’informatique et de recherche opérationnelle IFT 6800 – Démonstration 5 But de la démonstration Cette démonstration est la deuxième partie d’une introduction aux bases du langage Java. Elle présente les classes et les objets. Préalables Révisez les notes de cours des séances 6 et 7 du cours. Classes et objets Java est un langage orienté objet, ce qui veut dire que le programmeur définit, crée et manipule des objets dans son code. Déclaration de classes Une classe est la définition d’une structure contenant des champs (des données) est des méthodes (des fonctions qui agissent sur des données). Une classe est donc une espèce de patron (« template ») qui permet la création d’objets (d’instances) qui suivront ce patron. Par exemple, on peut définir la structure de base d’une classe Chien (taille, race, etc.). Ensuite, il est possible de créer des objets de ce type Chien, par exemple Fido (petite taille, race terrier), ou Médor (saint-bernard, grande taille). Déclaration simple Avant d’utiliser une classe, il faut définir son type en la déclarant. Rappelez-vous que toute classe de nom NomClasse doit apparaître dans un fichier NomClasse.java (attention à la casse). Pour définir une classe, on écrit le mot-clé class suivi du nom de la classe puis d’un bloc entre accolades contenant les déclarations de champs et de méthodes. Par exemple, pour créer un compte bancaire, on peut créer une classe Compte dans un fichier Compte.java. class Compte { // on met ici des champs et des méthodes } Champs Les données d’une classe sont contenues dans des champs, qui sont des variables. La déclaration se fait en donnant le type du champ suivi de son nom. Par exemple, pour créer une classe représentant un compte bancaire : class Compte { double solde; } Méthodes La déclaration se fait en donnant le type de retour suivi du nom et de parenthèses entourant les paramètres. Attention, les parenthèses doivent être présentes même s’il n’y a pas de paramètres. La déclaration est suivie d’un bloc d’instructions entre accolades qui définit ce que fait la méthode. La valeur de retour est introduite par le mot-clé return. Celui-ci peut être omis si le type de retour est void. Par exemple, ajoutons la méthode setSolde à la classe Compte. class Compte { double solde; void setSolde( double nouveauSolde ) { solde = nouveauSolde; } } On peut mettre plusieurs instructions dans un méthode donnée. Ainsi, on peut raffiner notre méthode setSolde en avertissant le programmeur lorsqu’il donne un solde négatif à un nouveau compte. class Compte { double solde; void setSolde( double nouveauSolde ) { if ( nouveauSolde < 0 ) { System.err.println( "Nouveau solde négatif !!" ); } solde = nouveauSolde; } } 2 On peut aussi demander le solde dans un objet Compte en créant une méthode getSolde : class Compte { double solde; void setSolde( double nouveauSolde ) { ... } double getSolde() // pas de paramètres passés à la méthode { return solde; } } Les paramètres sont toujours transmis par valeur pour les types de données de base. Par contre, les instances passées en paramètres sont transmises par référence et sont donc susceptibles d’être modifiées. La méthode main On comprend mieux maintenant la syntaxe de la méthode main de nos programmes précédents : public static void main( String[] args ) { ... } Pour qu’une classe puisse être exécutée, comme un programme, avec la commande java NomClasse, il faut que cette méthode se trouve dans la classe NomClasse, telle quelle. Constructeurs Les constructeurs sont des méthodes spéciales qui permettent d’initialiser les champs d’une classe lorsqu’on crée une instance d’un objet. On les déclare en utilisant le nom de la classe suivi de parenthèses entourant les paramètres. Par exemple, on peut construire un nouvel objet Compte en lui donnant un paramètre soldeInitial. 3 class Compte { double solde; Compte( double soldeInitial ) { solde = soldeInitial; } void setSolde( double nouveauSolde ) { ... } double getSolde() // pas de paramètres passés à la méthode { return solde; } } Contrôle de visibilité Il existe 4 niveaux de protection des champs et des méthodes d’une classe. Nous en verrons deux : public et private. public : La déclaration est introduite par le mot-clé public. Il n’y a aucune restriction d’accès. private : La déclaration est introduite par le mot-clé private. Seule la classe peut voir les champs private et invoquer les méthodes déclarées private. En général on prévoit des méthodes public d’accès aux données private. Dans notre exemple, le champ solde doit être caché (private) et n’être accessible que par les méthodes getSolde et setSolde (qui doivent donc être public). class Compte { private double solde; public Compte( double soldeInitial ) { solde = soldeInitial; } public void setSolde( double nouveauSolde ) { ... } public double getSolde() // pas de paramètres passés à la méthode { return solde; } } 4 Pour protéger les champs à l’intérieur d’une classe d’une manipulation erronée ou malveillante par un programmeur, il est fortement recommandé que ces champs soient déclarés private. On appelle ce principe l’encapsulation des données. Nous évaluerons ceci lors de la correction de vos devoirs. Exercices 1. Créez une classe Chat contenant deux champs : un nom (un champ de type String) et un age (un champ de type int). Assurez-vous d’utiliser les bonnes visibilités (public ou private). N’utilisez pas d’accent dans le nom de la variable age. Compilez la classe Chat en utilisant le compilateur Java javac. (Avez-vous fait inclure jdk avant ?). Vous ne pouvez l’exécuter pour le moment. 2. Créez le constructeur de Chat, qui prend en paramètre son nom et son âge. Le constructeur doit émettre un message d’avertissement si vous donnez un âge inférieur ou égal à 0. 3. Créez une méthode miaou, qui prend en paramètre un entier n et qui affiche à l’écran la chaîne « nomDuChat dit Miaou ! » n fois, où nomDuChat est le nom du chat. Création d’instances La création d’une instance se fait via l’opérateur new qui procède à l’allocation de mémoire et à l’appel d’un constructeur. On crée un nouvel objet de classe NomClasse avec une instruction ressemblant à ceci : NomClasse nomVariable = new NomClasse(paramètres du constructeur); Par exemple, pour créer un objet de type Compte, avec un solde initial de 100 $ on ferait : Compte monCompte = new Compte(100.00); On pourrait aussi faire suivre cette instruction par la création d’un autre compte : Compte monAutreCompte = new Compte(200.00); On peut aussi créer des tableaux d’objets, comme on l’a vu dans la section précédente sur les tableaux : Compte[] mesComptes = new Compte[2]; mesComptes[0] = new Compte(18.00); // le 1er élément est initialisé mesComptes[1] = new Compte(135.07); // le 2e élément est initialisé Accès aux champs et aux méthodes On accède aux champs et aux méthodes en utilisant la notation pointée. 5 Pour accéder aux champs ou aux méthodes d’une instance de classe (d’un objet), on fait : nomVariableObjet.nomDuChamp // accéder au champ nomDuChamp de l'objet ou nomVariableObjet.nomMéthode(paramètres) // appel de nomMéthode Par exemple, pour invoquer la méthode getSolde du compte monCompte, on ferait : monCompte.getSolde() // ceci retourne le solde courant Pour fixer le solde de ce même compte, on ferait : monCompte.setSolde( 120.00 ) Pour accéder à ces champs et méthodes, il faut que leur visibilité le permette. Dans notre cas, cela veut dire que le champ doit être public. Si on avait essayé d’accéder au solde en utilisant l’accès au champ solde, directement : monCompte.solde le compilateur aurait refusé de compiler le programme. Exercices 4. Créez un programme Zoo qui pourra être lancé (donc, qui contient une méthode public static void main(String[] args)). Dans ce programme, créez deux objets de type Chat, qui seront affectés à deux variables, chat1 et chat2. Donnez-leur les noms et âges que vous voudrez. Pour compiler votre programme, il faut maintenant faire javac Chat.java Zoo.java pour que le compilateur soit au courant de toutes les classes en jeu dans votre programme. 5. Appelez la méthode miaou sur le premier chat, dans votre programme Zoo et lancez le programme Zoo. 6. Ajoutez une ligne qui tente d’accéder au champ age de chat1 et compilez. Que se passe-t-il ? 7. Ajoutez une méthode getAge dans la classe Chat qui vous permettra d’accéder à l’âge d’un chat et ajoutez une instruction dans le programme Zoo qui affichera la somme des âges de chat1 et chat2. Lancez le programme Zoo. Documentation sur les classes Comment savoir quelles sont les méthodes à la disposition du programmeur, pour une classe donnée ? Tout est documenté via la javadoc (la documentation Java). Par exemple, toute la javadoc sur les classes utilisées couramment est disponible sur le site http://java.sun.com/j2se/1.5.0/docs/api/ Le volet gauche indique les classes auxquelles vous avez accès, et le volet droit décrit la classe sélectionnée dans le volet gauche. Vous avez notamment de la documentation sur 6 les constructeurs d’une classe, et sur ses méthodes. Les détails incluent le nombre et le type de paramètres des méthodes et constructeurs, ainsi que les types retournés par une méthode donnée. Exercices 8. Trouvez dans la javadoc la méthode qui permet de déterminer la longueur d’un objet String (une chaîne de caractères). 9. Créez une méthode private detailsSurNom dans la classe Chat, qui affiche la longueur du nom du chat et qui affiche la première lettre de son nom. 10. Essayez d’invoquer la méthode detailsSurNom à partir de Zoo. Que se passe-til ? 11. Invoquez la méthode detailsSurNom à partir du constructeur de Chat, et relancez votre programme. Sources Rédigé par Fabrizio Gotti, automne 2007. La première partie de ce document est inspirée d’une démonstration précédente. 7