Programmation Java pour les enfants, les parents et les grands-parents


précédentsommairesuivant

XII. Chapitre 10. Autres briques de base Java

Nous avons eu l'occasion d'utiliser pas mal d'éléments Java différents dans les chapitres précédents. Nous avons même créé un jeu de morpion. Mais j'ai laissé de côté d'importants éléments et techniques Java et il est temps de corriger ces omissions.

XII-A. Utilisation des valeurs de date et d'heure

Tous les ordinateurs ont une horloge interne. N'importe quel programme Java peut déterminer la date et l'heure courantes et les afficher dans différents formats, par exemple "15/06/2004" ou "15 juin 2004". De nombreuses classes Java permettent de gérer les dates et les heures, mais deux d'entre elles, java.util.Date et java.text.SimpleDateFormat, suffiront à couvrir la plupart de tes besoins.

Il est facile de créer un objet qui stocke les date et heure système courantes précises à la milliseconde près :

 
Sélectionnez
Date maintenant = new Date();
System.out.println("Nous sommes le " + SimpleDateFormat.getDateInstance().format(maintenant)));

La sortie de ces lignes peut ressembler à ceci (7) :

 
Sélectionnez
Nous sommes le 23 juin 2005

La classe SimpleDateFormat permet d'afficher les dates et les heures selon différents formats. D'abord, tu dois créer une instance de cette classe avec le format souhaité. Ensuite, appelle sa méthode format() en lui passant un objet Date en argument. Le programme suivant formate et affiche la date courante sous différents formats.

 
Sélectionnez
import java.util.Date;
import java.text.SimpleDateFormat;

public class MonFormatDate {

  public static void main( String [] args ) {
    // Crée un objet Date 
    // et l'affiche dans le format par défaut
    Date maintenant = new Date();
    System.out.println("Nous sommes le : " + 
       SimpleDateFormat.getDateInstance().format(maintenant));
	
    // Affiche la date comme ceci : 23-06-05 
    SimpleDateFormat formatDate = 
                            new SimpleDateFormat("dd-MM-yy"); 
    String dateFormatée = formatDate.format(maintenant);
    System.out.println("Nous sommes le (jj-MM-aa) : " 
	                                       + dateFormatée);
	                
    // Affiche la date comme ceci : 23-06-2005                
    formatDate = new SimpleDateFormat("dd/MM/yyyy"); 
    dateFormatée = formatDate.format(maintenant);
    System.out.println("Nous sommes le (jj/MM/aaaa) : " 
    			                           + dateFormatée);
							
    // Affiche la date comme ceci : jeudi 23 juin 2005
    formatDate = new SimpleDateFormat("EEEE d MMM yyyy"); 
    dateFormatée = formatDate.format(maintenant);
    System.out.println("Nous sommes le (JJJJ jj MMMM aaaa) : " 
                                             + dateFormatée);
    // Affiche l'heure comme ceci : 20h 30m 17s	 
    formatDate = new SimpleDateFormat("kk'h' mm'm' ss's'"); 
    dateFormatée = formatDate.format(maintenant);
    System.out.println("Il est (HHh MMm SSs) : " 
		                                 + dateFormatée);    
  }
}

Compile et exécute la classe MonFormatDate. Elle affiche ceci :

 
Sélectionnez
Nous sommes le : 23 juin 2005
Nous sommes le (jj-MM-aa) : 23-06-05
Nous sommes le (jj/MM/aaaa) : 23/06/2005
Nous sommes le (JJJJ jj MMMM aaaa) : jeudi 23 juin 2005
Il est (HHh MMm SSs) : 20h 30m 17s

La documentation Java de la classe SimpleDateFormat décrit d'autres formats. Tu peux aussi trouver d'autres méthodes de gestion des dates dans la classe java.util.Calendar.

XII-B. Surcharge de méthode

Il peut y avoir, dans une même classe, plusieurs méthodes de même nom mais ayant des listes d'arguments différentes. C'est ce qu'on appelle la surcharge de méthode (method overloading). Par exemple, la méthode println() de la classe System peut être appelée avec différents types d'arguments : String, int, char, etc.

 
Sélectionnez
System.out.println("Bonjour");

System.out.println(250);

System.out.println('A');

Même s'il semble que l'on appelle trois fois la même méthode println(), il s'agit en fait de trois méthodes différentes. Tu te demandes peut-être pourquoi on ne crée pas des méthodes avec des noms différents, par exemple printString(), printInt() et printChar() ? Une raison en est qu'il est plus facile de mémoriser un nom de méthode d'affichage plutôt que plusieurs. Il y a d'autres raisons justifiant l'utilisation de la surcharge de méthode, mais elles sont un peu compliquées à expliquer et sont abordées dans des livres d'un niveau plus avancé.

Tu te rappelles notre classe Poisson du Chapitre 4 et sa méthode plonger(), qui attend un argument :

 
Sélectionnez
public int plonger(int combienDePlus)

Créons une autre version de cette méthode qui n'aura pas besoin d'argument. Cette méthode va forcer le poisson à plonger de cinq mètres, sauf si la profondeur courante vient à dépasser 100 mètres. La nouvelle version de la classe Poisson a une nouvelle variable invariante, PROFONDEUR_PLONGEE, dont la valeur est cinq.

La classe Poisson a maintenant deux méthodes plonger() surchargées.

 
Sélectionnez
public class Poisson extends AnimalFamilier {
  int profondeurCourante = 0;
  final int PROFONDEUR_PLONGEE = 5; 

  public int plonger() {
    profondeurCourante = profondeurCourante +           
                                         PROFONDEUR_PLONGEE;
    if (profondeurCourante > 100) {
      System.out.println("Je suis un petit" 
                      + " poisson et je ne peux pas plonger" 
          + " plus profond que 100 mètres");
      profondeurCourante = profondeurCourante 
                                       - PROFONDEUR_PLONGEE;
    } else {
      System.out.println("Plongée de " + PROFONDEUR_PLONGEE     
                                               + " mètres");
      System.out.println("Je suis à " + profondeurCourante
                      + " mètres sous le niveau de la mer");
    }
    return profondeurCourante; 
  }
  public int plonger(int combienDePlus) {
    profondeurCourante = profondeurCourante + combienDePlus;
    if (profondeurCourante > 100) {
      System.out.println("Je suis un petit" 
                      + " poisson et je ne peux pas plonger" 
                      + " plus profond que 100 mètres");
      profondeurCourante = profondeurCourante 
                                            - combienDePlus;
    } else {
      System.out.println("Plongée de " + combienDePlus
                                               + " mètres");
      System.out.println("Je suis à " + profondeurCourante
                      + " mètres sous le niveau de la mer");
    }
    return profondeurCourante; 
  }
	
  public String dire(String unMot){
    return "Ne sais-tu pas que les poissons ne"
                                         + " parlent pas ?";
  } 
  // Constructeur
  Poisson(int positionDépart) {
    profondeurCourante = positionDépart;
  }
}

MaîtrePoisson peut désormais appeler l'une ou l'autre des méthodes plonger()surchargées :

 
Sélectionnez
public class MaîtrePoisson {

  public static void main(String[] args) {
		
    Poisson monPoisson = new Poisson(20);
		
    monPoisson.plonger(2);
		
    monPoisson.plonger();  // nouvelle méthode surchargée		
    monPoisson.plonger(97);
    monPoisson.plonger(3);
		
    monPoisson.dormir();
  }
}

Les constructeurs peuvent aussi être surchargés, mais l'un d'entre eux seulement est utilisé lorsqu'un objet est créé. Java appelle le constructeur qui a la bonne liste d'arguments. Par exemple, si tu ajoutes un constructeur sans argument à la classe Poisson, MaîtrePoisson peut en créer une instance par l'un des moyens suivants :

 
Sélectionnez
Poisson monPoisson = new Poisson(20);

ou

 
Sélectionnez
Poisson monPoisson = new Poisson();

XII-C. Lecture des entrées clavier

Dans cette section, tu vas apprendre comment un programme peut afficher des questions dans la fenêtre de commande et comprendre les réponses que l'utilisateur entre au clavier. Cette fois, nous allons retirer de la classe MaîtrePoisson toutes les valeurs codées en dur qu'il passait à la classe Poisson. Le programme va maintenant demander "De combien ?" et le poisson va plonger en fonction des réponses de l'utilisateur.

A ce stade, tu dois être plutôt à l'aise dans l'utilisation de la sortie standard (standard output) System.out. A propos, la variable out est du type java.io.OutputStream. Je vais maintenant t'expliquer comment utiliser l'entrée standard (standard input) System.in. Au fait, comme tu peux t'en douter, le type de données de la variable in est java.io.InputStream.

La version suivante de la classe MaîtrePoisson affiche une invite de commande (prompt) sur la console système et attend la réponse de l'utilisateur. Une fois que l'utilisateur a tapé un ou plusieurs caractères et appuyé sur la touche Entrée, Java place ces caractères dans l'objet InputStream pour les passer au programme.

 
Sélectionnez
import java.io.IOException;
import java.io.BufferedReader;
import java.io.InputStreamReader;

public class MaîtrePoisson {

  public static void main(String[] args) {
		
    Poisson monPoisson = new Poisson(20);
    String chaîneNombreDeMètres = "";
    int entierNombreDeMètres;
    // Crée un lecteur de flux d'entrée connecté à 
    // System.in et le passe au lecteur à tampon
    BufferedReader entréeStandard = new BufferedReader
			       (new InputStreamReader(System.in));
		
    // Continue à plonger tant que l'utilisateur 
    // ne tape pas "Q"
    while (true) {
      System.out.println("Prêt à plonger. De combien ?");
      try {
        chaîneNombreDeMètres = entréeStandard.readLine();
        if (chaîneNombreDeMètres.equals("Q")) {
          // Sort du programme
          System.out.println("Au revoir !");
          System.exit(0);
	  } else {
	    // Convertit chaîneNombreDeMètres en entier
	    // et plonge de la valeur de entierNombreDeMètres
          entierNombreDeMètres =  
                     Integer.parseInt(chaîneNombreDeMètres);
          monPoisson.plonger(entierNombreDeMètres);
        }
	} catch (IOException e) {
        e.printStackTrace();
	}
    } // Fin du while
  } // Fin de main
}

Un dialogue entre l'utilisateur et le programme MaîtrePoisson ressemble à ceci :

 
Sélectionnez
Prêt à plonger. De combien ?
14
Plongée de 14 mètres
Je suis à 34 mètres sous le niveau de la mer
Prêt à plonger. De combien ?
30
Plongée de 30 mètres
Je suis à 64 mètres sous le niveau de la mer
Prêt à plonger. De combien ?
Q
Au revoir !

En premier lieu, MaîtrePoisson crée un flux BufferedReader connecté à l'entrée standard System.in. Il affiche ensuite le message "Prêt à plonger. De combien ?" et la méthode readLine() met le programme en attente jusqu'à ce que l'utilisateur appuie sur Entrée. La valeur saisie est passée au programme sous forme de String, que MaîtrePoisson convertit en entier avant d'appeler la méthode plonger() de la classe Poisson.

Ces actions sont répétées en boucle jusqu'à ce que l'utilisateur tape la lettre Q pour quitter le programme. La ligne chaîneNombreDeMètres.equals("Q") compare la valeur de la variable de type String chaîneNombreDeMètres avec la lettre Q.

Nous avons utilisé la méthode readLine() pour lire en une seule fois toute la ligne entrée par l'utilisateur, mais il existe une autre méthode, System.in.read(), qui permet de traiter les entrées de l'utilisateur caractère par caractère.

XII-D. Compléments sur les paquetages Java

Quand les programmeurs travaillent sur des projets de grande taille, contenant de nombreuses classes, ils les organisent généralement en différents paquetages (packages). Par exemple, un paquetage pourrait contenir toutes les classes qui affichent les fenêtres (écrans), alors qu'un autre contiendrait tous les récepteurs d'événements. Java aussi range ses classes dans des paquetages, tels que java.io pour les classes responsables des opérations d'entrée/sortie ou javax.swing pour les classes Swing.

Créons un nouveau projet Eclipse appelé Ping Pong. Ce projet organisera ses classes en deux paquetages : écrans et moteur. Crée la classe TablePingPong et entre le mot écrans dans le champ Package :

Image non disponible

Appuie sur le bouton Fin et Eclipse génère un code qui inclut une ligne contenant le nom du paquetage.

 
Sélectionnez
package écrans;

public class TablePingPong {

  public static void main(String[] args) {
  }

}

A propos, si ta classe inclut une ligne avec le mot-clé package, tu n'as le droit d'écrire que des commentaires au-dessus de cette ligne.

Comme chaque paquetage est stocké dans un répertoire différent du disque, Eclipse crée le répertoire écrans et y place le fichier TablePingPong.java. Vérifie - il doit y avoir sur ton disque un répertoire c:\eclipse\plan de travail\Ping Pong\écrans, contenant les fichiers TablePingPong.java et TablePingPong.class.

Image non disponible

Crée maintenant une autre classe, nommée MoteurPingPong, et indique moteur comme nom de paquetage. Le projet Ping Pong contient maintenant deux paquetages :

Image non disponible

Puisque nos deux classes sont situées dans deux paquetages (et répertoires) différents, la classe TablePingPong ne peut voir la classe MoteurPingPong que si tu ajoutes une instruction import.

 
Sélectionnez
package écrans;

import moteur.MoteurPingPong;

public class TablePingPong {

  public static void main(String[] args) {
    MoteurPingPong moteurJeu = new MoteurPingPong();
  }
}

Non seulement les paquetages Java t'aident-ils à mieux organiser tes classes, mais ils peuvent aussi être utilisés pour limiter l'accès à leurs classes par des "étrangers" installés dans d'autres paquetages.

XII-E. Niveaux d'accès

Les classes, méthodes et variables membres Java peuvent avoir les niveaux d'accès public, private, protected et package. Notre classe MoteurPingPong a le niveau d'accès public, ce qui signifie que n'importe quelle classe peut y accéder. Faisons une petite expérience : ôtons le mot-clé public de la déclaration de la classe MoteurPïngPong. La classe TablePingPong ne peut même plus compiler ; le message d'erreur MoteurPingPong ne peut pas être résolu ou ne correspond pas à un type signifie que la classe TablePingPong ne voit plus la classe MoteurPingPong.

Si aucun niveau d'accès n'est spécifié, la classe a un niveau d'accès package, c'est-à-dire qu'elle n'est accessible qu'aux classes du même paquetage.

De la même façon, si tu oublies de donner un accès public aux méthodes de la classe MoteurPingPong, TablePingPong se plaindra en disant que ces méthodes ne sont pas visibles. Tu verras comment les niveaux d'accès sont utilisés dans le prochain chapitre, en créant le jeu de ping pong.

Image non disponible

Le niveau d'accès private est utilisé pour cacher les variables ou méthodes de la classe aux yeux du monde extérieur. Pense à une voiture : la plupart des gens n'ont aucune idée de tout ce qui se cache sous le capot ou de ce qui se passe quand le conducteur appuie sur la pédale de frein.

Examine l'exemple de code suivant - en Java, on peut dire que l'objet Voiture expose une seule méthode publique - freiner(), qui en interne peut appeler plusieurs autres méthodes qu'un conducteur n'a pas besoin de connaître. Par exemple, si le conducteur appuie trop fort sur la pédale, l'ordinateur de bord peut mettre en action des freins spéciaux anti-blocage. J'ai déjà dit auparavant que des programmes Java contrôlaient des robots aussi compliqués que ceux de la mission Mars Rovers, sans même parler des simples voitures.

 
Sélectionnez
public class Voiture {
  
  // Cette variable privée ne peut être utilisée 
  // qu'à l'intérieur de cette classe
  private String conditionFreins;

  // La méthode publique freiner() appelle des méthodes 
  // privées pour décider quels freins utiliser
  public void freiner(int pressionPédale) {
    boolean utiliserFreinsNormaux; 
    utiliserFreinsNormaux =
              vérifierBesoinABS(pressionPédale);
		
    if (utiliserFreinsNormaux == true) {
      utiliserFreinsNormaux(); 
    } else {
      utiliserFreinsAntiBlocage();
    }
  }

  // Cette méthode privée ne peut être appelée 
  // qu'à l'intérieur de cette classe
  private boolean vérifierBesoinABS(int pression) {
    if (pression > 100) {
      return true;
    } else {
      return false;
    }
  }

  // Cette méthode privée ne peut être appelée 
  // qu'à l'intérieur de cette classe
  private void utiliserFreinsNormaux() {
    // Code qui envoie un signal aux freins normaux
  }

  // Cette méthode privée ne peut être appelée 
  // qu'à l'intérieur de cette classe
  private void utiliserFreinsAntiBlocage() {
    // Code qui envoie un signal aux freins anti-blocage
  }
}

Le dernier mot-clé Java pour contrôler le niveau d'accès est protected. Si tu utilises ce mot-clé dans la signature d'une méthode, celle-ci est visible à l'intérieur de la classe, de ses sous-classes et des autres classes du même paquetage. Mais elle n'est pas utilisable par les classes indépendantes situées dans d'autres paquetages.

L'une des caractéristiques principales des langages orientés objet est appelée encapsulation, c'est-à-dire la capacité à cacher et protéger les éléments d'une classe.

Quand tu conçois une classe, cache les méthodes et les variables membres qui ne doivent pas être visibles de l'extérieur. Si les concepteurs de voitures ne masquaient pas une partie des contrôles de la mécanique, le conducteur devrait gérer des centaines de boutons, d'interrupteurs et de jauges.

Image non disponible

Dans la section suivante, la classe Score masque ses attributs en les déclarant private.

XII-F. Retour sur les tableaux

Le programme EnregistreurScores du Chapitre 9 crée un tableau d'objets String pour stocker les noms et les scores des joueurs dans un fichier. Il est temps d'apprendre à utiliser des tableaux pour stocker tous types d'objets.

Cette fois, nous allons créer un objet représentant un score et lui donner des attributs tels que les nom et prénom du joueur, son score et la date de sa dernière partie.

La classe Score ci-dessous définit des méthodes d'accès en lecture et en écriture (getters et setters) pour chacun des ses attributs, qui sont déclarés privés. Bon, il n'est peut-être pas évident de comprendre pourquoi la classe appelante ne peut pas simplement affecter la valeur de l'attribut score comme ceci :

 
Sélectionnez
Score.score = 250;

au lieu de :

 
Sélectionnez
Score.affecterScore(250);

Essaie d'élargir ton horizon. Imagine que, plus tard, nous décidions que notre programme doive jouer un morceau de musique quand un joueur atteint le score de 500 ? Si la classe Score a une méthode affecterScore(), il suffit de modifier cette méthode en lui ajoutant le code qui vérifie le score et joue de la musique si nécessaire. La classe appelante appelle toujours de la même façon la version musicale de la méthode affecterScore(). Si la classe appelante affectait directement la valeur, elle devrait elle-même implanter les changements musicaux. Et si tu voulais réutiliser la classe Score dans deux programmes de jeu différents ? En utilisant la modification directe d'attributs, tu devrais implanter les changements dans deux classes appelantes, alors qu'une méthode d'affectation encapsule les changements qui sont immédiatement fonctionnels pour chaque classe appelante.

 
Sélectionnez
import java.util.Date;
import java.text.SimpleDateFormat;

public class Score {
  private String prénom;
  private String nom;
  private int score;
  private Date dateDernièrePartie;
  
  public String lirePrénom() {
    return prénom;
  }
  public void affecterPrénom(String prénom) {
    this.prénom = prénom;
  }
  public String lireNom() {
    return nom;
  }
  public void affecterNom(String nom) {
    this.nom = nom;
  }
  public int lireScore() {
    return score;
  }
  public void affecterScore(int score) {
    this.score = score;
  }
  public Date lireDateDernièrePartie() {
    return dateDernièrePartie;
  }
  public void affecterDateDernièrePartie(Date   
                                    dateDernièrePartie) {
    this.dateDernièrePartie = dateDernièrePartie;
  }
  // Concatène tous les attributs en une chaîne 
  // et y ajoute un caractère fin de ligne. 
  // Cette méthode est pratique, par exemple pour 
  // afficher toutes les valeurs d'un coup, comme ceci :
  // System.out.println(myScore.toString());
  // NDT : comme cette méthode redéfinit Object.toString(),
  // tu es certain que la bonne représentation de Score 
  // est utilisée partout  Java en a besoin (c'est pour 
  // cela que nous ne l'avons pas appelée convertirEnString).
  public String toString() {
    String chaîneScore = prénom + " " + 
        nom + " " +  score + " " + SimpleDateFormat.
        getDateInstance().format(dateDernièrePartie) +  
        System.getProperty("line.separator"); 
    return chaîneScore; 
  }
}

Le programme EnregistreurScores2 crée des instances de l'objet Score et affecte des valeurs à leurs attributs.

 
Sélectionnez
import java.io.FileWriter;
import java.io.BufferedWriter;
import java.io.IOException;
import java.util.Date;

public class EnregistreurScores2 {

  /**
   La méthode main exécute les actions suivantes : 
   1. Crée une instance de tableau
   2. Crée les objets Score et les stocke dans le tableau
   3. Ecrit les données de scores dans un fichier 
  */
  public static void main(String[] args) {
		
    FileWriter monFichier = null;
    BufferedWriter tampon = null;
	
    Date ceJour = new Date();
    Score scores[] = new Score[3];
	
    // Joueur n°1
    scores[0]= new Score(); 
    scores[0].affecterPrénom("Jean");
    scores[0].affecterNom("Dupont");
    scores[0].affecterScore(250);
    scores[0].affecterDateDernièrePartie(ceJour);
	
    // Joueur n°2
    scores[1]= new Score(); 
    scores[1].affecterPrénom("Anne");
    scores[1].affecterNom("Durand");
    scores[1].affecterScore(300);
    scores[1].affecterDateDernièrePartie(ceJour);
		
    // Joueur n°3 
    scores[2]= new Score();
    scores[2].affecterPrénom("Eskil");
    scores[2].affecterNom("Pemieufer");
    scores[2].affecterScore(190);
    scores[2].affecterDateDernièrePartie(ceJour);

	try {
      monFichier = new FileWriter("c:\\scores2.txt");
      tampon = new BufferedWriter(monFichier);
		
      for (int i = 0; i < scores.length; i++) {
        // Convertit chaque Score en String 
	  // et l'écrit dans scores2.txt 
 	  tampon.write(scores[i].toString());
 	  System.out.println("Ecriture des données de " + 
                                       scores[i].lireNom());
      }
      System.out.println("Ecriture du fichier terminée");
    } catch (IOException e) {
      e.printStackTrace();
    } finally {
      try {
        tampon.flush();	
        tampon.close();
        monFichier.close();
      } catch (IOException e1) {
        e1.printStackTrace();
      }
    }
  }
}

Si un programme essaie d'accéder à un élément du tableau dont l'indice est trop grand, par exemple ici scores[5].lireNom(), Java lève l'exception ArrayIndexOutOfBoundsException.

XII-G. Classe ArrayList

Le paquetage java.util contient des classes plutôt pratiques pour stocker plusieurs instances (des collections) d'objets en mémoire. Certaines des collections populaires de ce paquetage sont les classes ArrayList (liste stockée dans un tableau), Vector (vecteur), Hashtable et HashMap (deux sortes de tables de hachage) et List (liste). Je vais te montrer comment utiliser la classe java.util.ArrayList.

L'inconvénient des tableaux normaux est que tu dois connaître à l'avance le nombre d'éléments du tableau. Rappelle-toi, pour créer une instance de tableau, tu dois mettre un nombre entre les crochets :

 
Sélectionnez
String[] mesAmis = new String[5];

La classe ArrayList n'a pas cette contrainte. Tu peux créer une instance de cette collection sans savoir combien d'objets il y aura : ajoute simplement de nouveaux éléments quand tu en as besoin.

Pourquoi utiliser des tableaux, alors, et ne pas utiliser systématiquement des ArrayList ? Malheureusement, rien n'est gratuit et il faut payer le prix du confort : ArrayList est un peu plus lent qu'un tableau normal et on ne peut y stocker que des objets, pas des nombres de type int.

Pour créer et remplir un objet ArrayList, il faut l'instancier, créer des instances des objets que tu souhaites y stocker, puis les ajouter à l'ArrayList en appelant sa méthode add(). Le petit programme ci-dessous remplit un ArrayList avec des objets de type String puis affiche le contenu de cette collection.

 
Sélectionnez
import java.util.ArrayList;

public class DémoArrayList {
  public static void main(String[] args) {
    // Crée et remplit un ArrayList
    ArrayList amis = new ArrayList();
    amis.add("Marie");
    amis.add("Anne");
    amis.add("David");
    amis.add("Rémi");
	
    // Combien d'amis y a-t-il ?
    int nombreAmis = amis.size();  
	 
    // Affiche le contenu de l'ArrayList
    for (int i = 0; i < nombreAmis; i++) {
    	System.out.println("L'ami(e) " + i + " est " 
    	                                        + amis.get(i));
    }
  }
}

Ce programme affiche les lignes suivantes :

 
Sélectionnez
L'ami(e) n°0 est Marie
L'ami(e) n°1 est Anne
L'ami(e) n°2 est David
L'ami(e) n°3 est Rémi

La méthode get() extrait d'un ArrayList l'élément situé à une position donnée. Puisqu'on peut stocker n'importe quel objet dans une collection, la méthode get() renvoie chaque élément comme un Object Java ; le programme a la responsabilité de convertir explicitement cet objet en un type de données approprié. Nous n'avons pas besoin de le faire dans l'exemple précédent uniquement parce que nous stockons des objets de type String dans la collection amis et que Java convertit automatiquement Object en String. Mais si tu stockes d'autres objets dans un ArrayList, par exemple des instances de la classe Poisson, le code correct pour ajouter et extraire un Poisson ressemble plutôt à celui du programme BocalAPoissons ci-dessous. Le programme crée une paire d'instances de la classe Poisson, affecte des valeurs à leurs attributs couleur, poids et profondeurCourante, puis les stocke dans l'ArrayList bocalAPoissons. Le programme extrait ensuite les objets de cette collection, convertit chacun d'entre eux en Poisson et affiche les valeurs de ses attributs.

 
Sélectionnez
import java.util.ArrayList;

public class BocalAPoissons {
  public static void main(String[] args) {
    ArrayList bocalAPoissons = new ArrayList();
    Poisson lePoisson;
	       
    Poisson unPoisson = new Poisson(20);
	
    unPoisson.couleur = "Rouge";
    unPoisson.poids = 1;
    bocalAPoissons.add(unPoisson);
  
    unPoisson = new Poisson(10); 
    unPoisson.couleur = "Vert";
    unPoisson.poids = 2;
    bocalAPoissons.add(unPoisson);
	
    int nombrePoissons = bocalAPoissons.size();
	
    for (int i = 0; i < nombrePoissons; i++) {
      lePoisson = (Poisson) bocalAPoissons.get(i);
      System.out.println("Attrapé le poisson " +   
        lePoisson.couleur + " qui pèse " +
        lePoisson.poids + " livres. Profondeur : " +  
        lePoisson.profondeurCourante);
    }
  }
}

Voici la sortie du programme BocalAPoissons :

 
Sélectionnez
Attrapé le poisson Rouge qui pèse 1.0 livres. Profondeur : 20
Attrapé le poisson Vert qui pèse 2.0 livres. Profondeur : 10

Maintenant que tu connais les niveaux d'accès Java, on peut modifier un peu les classes AnimalFamilier et Poisson. Des variables telles que age, couleur, poids et taille devraient être déclarées comme protected et la variable profondeurCourante devrait être private. Tu dois ajouter de nouvelles méthodes publiques, telles que lireAge() pour renvoyer la valeur de la variable age et affecterAge() pour affecter la valeur de cette variable.

Les programmeurs élégants ne permettent pas à une classe de modifier directement les propriétés d'une autre ; la classe doit fournir les méthodes qui modifient ses internes. C'est pourquoi la classe Score de la section précédente est conçue avec des variables private, qui peuvent être modifiées et lues avec les méthodes d'accès appropriées.

Dans ce chapitre, je t'ai présenté divers éléments et techniques Java qui semblent sans relation les uns avec les autres. Mais tous ces éléments sont fréquemment utilisés par les programmeurs Java professionnels. Après avoir effectué les exercices pratiques de ce chapitre, tu devrais mieux comprendre comment tous ces éléments fonctionnent ensemble.

XII-H. Autres lectures

XII-I. Exercices

Image non disponible

1. Ajoute un constructeur surchargé sans argument à la classe Poisson. Ce constructeur doit initialiser à 10 mètres la profondeur de départ. La classe MaîtrePoisson va créer une instance de l'objet Poisson comme ceci :

 
Sélectionnez
Poisson monPoisson = new Poisson();

2. Ajoute un constructeur à quatre arguments à la classe Score. Crée un programme EnregistreurScores3 qui génère les instances des objets Score non pas en utilisant des méthodes d'affectation, mais plutôt au moment de la création des scores, comme ceci :

 
Sélectionnez

Score unScore = new Score(
	"Jean", "Dupont", 250, ceJour);

XII-J. Exercices pour les petits malins

Image non disponible

Regarde en ligne comment s'utilise la classe Vector et essaie de créer un programme DémoVector similaire au programme DémoArrayList.


précédentsommairesuivant
NDT le code minimal est encore plus simple pour nos amis anglophones, qui n'ont pas besoin de faire appel à SimpleDateFormat ; la ligne System.out.println("Date anglaise " + maintenant); imprimerait par exemple Date anglaise Thu Jun 23 11:48:55 CEST 2005.

Vous avez aimé ce tutoriel ? Alors partagez-le en cliquant sur les boutons suivants : Viadeo Twitter Facebook Share on Google+   

  

Copyright © 2015 Yakov Fain. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.