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


précédentsommairesuivant

V. Chapitre 3. Animaux familiers et poissons - Classes Java

Les programmes Java sont constitués de classes qui représentent des objets du monde réel. Même si chaque personne écrit des programmes à sa façon, presque tout le monde est d'accord pour reconnaître que la meilleure façon de le faire est d'employer le style dit orienté objet. Cela signifie que les bons programmeurs commencent par décider quels objets doivent être inclus dans le programme et quelles classes Java vont les représenter. Ce n'est qu'une fois cette étape menée à bien qu'ils commencent à écrire du code Java.

V-A. Classes et Objets

Image non disponible

Créons et discutons une classe nommée JeuVidéo. Cette classe peut avoir plusieurs méthodes, qui représentent les actions que les objets de cette classe peuvent effectuer : démarrer le jeu, l'arrêter, enregistrer le score, etc. Cette classe peut aussi posséder des attributs ou propriétés : prix, couleur de l'écran, nombre de télécommandes et autres.

Image non disponible

En langage Java, cette classe pourrait ressembler à ceci :

 
Sélectionnez
class JeuVidéo {
  String couleur;
  int prix;
    
  void démarrer () {
  }
  void arrêter () {
  }
  void sauverScore(String nomJoueur, int score) {
  }
}

Notre classe JeuVidéo est sans doute similaire aux autres classes qui représentent des jeux vidéo - ceux-ci ont tous des écrans de taille et de couleur différentes, effectuent des actions similaires et coûtent de l'argent.

Nous pouvons être plus spécifiques et créer une autre classe Java, nommée GameBoyAdvance. Elle appartient aussi à la famille des jeux vidéo, mais possède certaines propriétés spécifiques au modèle GameBoy Advance, par exemple un type de cartouche.

 
Sélectionnez
class GameBoyAdvance {
  String typeCartouche;
  int largeurEcran;
    
  void démarrerJeu() {
  }
  void arrêterJeu() {
  }
}

Dans cet exemple, la classe GameBoyAdvance définit deux attributs - typeCartouche et largeurEcran - et deux méthodes - démarrerJeu et arrêterJeu. Mais, pour l'instant, ces méthodes ne peuvent effectuer aucune action, parce qu'il n'y a pas de code Java entre leurs accolades.

Après le mot classe, tu dois maintenant t'habituer à la nouvelle signification du mot objet. La phrase "créer une instance d'un objet" signifie créer une copie de cet objet dans la mémoire de l'ordinateur en respectant la définition de sa classe.

Un plan de fabrication de la GameBoy Advance correspond à une console réelle de la même façon qu'une classe Java correspond à l'une de ses instances en mémoire. Le processus de fabrication des consoles réelles d'après ce plan est similaire au processus de création d'instances d'objets GameBoyAdvance en Java.

Image non disponible

La plupart du temps, un programme ne pourra utiliser une classe Java qu'après qu'une instance en ait été créée. De même, les fabricants créent des milliers de copies d'une console de jeu à partir d'une même description. Bien que ces copies représentent la même classe, leurs attributs peuvent avoir des valeurs différentes - certaines sont bleues alors que d'autres sont argentées, et ainsi de suite. En d'autres termes, un programme peut créer de multiples instances d'objets GameBoyAdvance.

V-B. Types de données

Les variables Java peuvent représenter les attributs d'une classe, les arguments d'une méthode ou être utilisées à l'intérieur d'une méthode pour stocker temporairement certaines données. Les variables doivent être déclarées avant de pouvoir être utilisées.

Te souviens-tu d'équations telles que y = x + 2 ? En Java, tu dois déclarer les variables x et y en précisant qu'elles appartiennent à un type de données numérique tel que int ou double :

 
Sélectionnez
int x;
int y;

Les deux lignes suivantes montrent comment tu peux affecter une valeur à ces variables. Si ton programme donne la valeur 5 à la variable x, la variable y sera égale à 7 :

 
Sélectionnez
x = 5;
y = x + 2;

En Java, tu peux aussi changer la valeur d'une variable d'une façon assez inhabituelle. Les deux lignes suivantes modifient la valeur de la variable y, qui passe de 5 à 6 :

 
Sélectionnez
int y = 5;
y++;

Bien qu'il y ait deux signes plus, Java va tout de même incrémenter la valeur de la variable y de 1.

Après le fragment de code suivant, la valeur de la variable monScore est aussi 6 :

 
Sélectionnez
int monScore = 5;
monScore = monScore + 1;

On peut utiliser de la même manière la multiplication, la division et la soustraction. Regarde l'extrait de code suivant :

 
Sélectionnez
int monScore = 10;

monScore--;
monScore = monScore * 2;
monScore = monScore / 3;

System.out.println("Mon score est " + monScore);

Qu'imprime ce code ? Eclipse a une fonctionnalité bien pratique appelée page de testeur de code, qui permet de tester rapidement n'importe quel bout de code (comme le précédent) sans même créer une classe. Sélectionne le menu Fichier, Nouveau, Autre…, puis Java, Exécution/Débogage Java, Page de testeur de code et entre le mot Test comme nom de ta page.

Entre maintenant dans la page ces cinq lignes de code utilisant monScore, sélectionne-les et clique sur la petite flèche verte accompagnée d'un J dans la barre d'outils.

Image non disponible

Pour voir le résultat des calculs, clique simplement sur l'onglet Console en bas de l'écran :

Mon score est 6

Dans cet exemple, l'argument de la méthode println() a été fabriqué en accolant deux morceaux - le texte "Mon score est " et la valeur de la variable monScore, c'est-à-dire 6. On appelle concaténation la création d'une chaîne de caractères (String) à partir de morceaux. Bien que monScore soit un nombre, Java est suffisamment malin pour convertir cette variable en String puis l'accoler au texte "Mon score est ".

Voyons d'autres façons de modifier les valeurs des variables :

 
Sélectionnez
monScore = monScore * 2; est équivalent à monScore *= 2;
monScore = monScore + 2; est équivalent à monScore += 2;
monScore = monScore - 2; est équivalent à monScore -= 2;
monScore = monScore / 2; est équivalent à monScore /= 2;

Il y a huit types de données simples, ou primaires en Java, et tu dois décider lequel utiliser en fonction du type et de la taille des données que tu as l'intention de stocker dans chaque variable :

  • Quatre types de données pour les valeurs entières - byte, short, int et long.
  • Deux types de données pour les valeurs décimales - float et double.
  • Un type de données qui permet de stocker un caractère isolé - char.
  • Un type de données logique nommé boolean qui autorise seulement deux valeurs : true (vrai) ou false (faux).

On peut affecter une valeur initiale à une variable lors de sa déclaration. On parle alors d'initialisation de la variable :

 
Sélectionnez
char niveau = 'E';
int chaises = 12;                            
boolean sonActif = false;         
double revenuNational = 23863494965745.78; 
float prixJeu = 12.50f;      
long totalVoitures = 4637283648392l; 

Dans les deux dernières lignes, f signifie float et l signifie long.

Si tu n'initialises pas les variables, Java le fera pour toi en donnant la valeur 0 à chaque variable numérique, la valeur false aux variables de type boolean et le code spécial '\u0000' aux variables de type char.

Il y a aussi le mot-clé spécial final ; s'il est utilisé dans la déclaration d'une variable, on ne peut affecter de valeur à cette variable qu'une fois, cette valeur ne pouvant plus être modifiée par la suite. Dans certains langages, les variables invariantes sont appelées constantes. En Java les noms des variables invariantes sont généralement écrits en lettres majuscules :

 
Sélectionnez
final String CAPITALE_ETAT = "Washington";

Outre les types de données primaires, on peut aussi utiliser les classes Java pour déclarer des variables. A chaque type de données primaire correspond une classe enveloppe, par exemple Integer, Double, Boolean, etc. Ces classes possèdent des méthodes utiles pour convertir les données d'un type à un autre.

Alors que le type de données char est utilisé pour stocker un caractère isolé, Java a aussi une classe String permettant de manipuler un texte plus long, par exemple :

 
Sélectionnez
String nom = "Dupont";

En Java, les noms de variables ne peuvent pas commencer par un chiffre ni contenir d'espaces.

Un bit est le plus petit bout de donnée que l'on puisse stocker en mémoire. Il contient soit 1, soit 0. Un octet (byte) est composé de huit bits. En Java, un char occupe deux octets en mémoire. En Java, un int ou un float occupe quatre octets. Les variables de type long ou double utilisent huit octets. Les types de données numériques qui utilisent plus d'octets peuvent stocker de plus grands nombres. 1 kilooctet (KO) correspond à 1024 octets. 1 mégaoctet (MO) correspond à 1024 kilooctets. 1 gigaoctet (GO) correspond à 1024 mégaoctets.

V-C. Création d'un animal familier

Nous allons concevoir et créer une classe AnimalFamilier. Tout d'abord, nous devons décider quelles actions notre animal familier sera capable d'effectuer. Que dirais-tu de manger, dormir et dire ? Nous allons programmer ces actions dans les méthodes de la classe AnimalFamilier. Nous allons aussi donner à notre animal les attributs suivants : âge, taille, poids et couleur.

Commençons par créer une nouvelle classe Java nommée AnimalFamilier dans Mon Premier Projet comme décrit dans le chapitre 2, mais sans cocher la case de création de la méthode main().

Ton écran devrait ressembler à ceci :

Image non disponible

Nous sommes maintenant prêts à déclarer les attributs et les méthodes de la classe AnimalFamilier. Le corps des méthodes et des classes Java est délimité par des accolades. A chaque accolade ouvrante doit correspondre une accolade fermante :

 
Sélectionnez
class AnimalFamilier {
}

Pour déclarer les variables constituant les attributs de la classe, nous devons choisir leur type. Prenons par exemple le type int pour l'âge, float pour la taille et le poids et String pour la couleur.

 
Sélectionnez
class AnimalFamilier {
  int âge;
  float poids;
  float taille;
  String couleur;
}

L'étape suivante consiste à ajouter des méthodes à notre classe. Avant de déclarer une méthode, il faut décider si elle prend des arguments et si elle retourne une valeur :

  • La méthode dormir() ne fera qu'afficher le message "Bonne nuit, à demain" - elle n'a pas besoin d'arguments et ne retourne aucune valeur.
  • Il en est de même pour la méthode manger(). Elle ne fera qu'afficher le message "J'ai si faim… Donne-moi un biscuit !".
  • La méthode dire() affichera aussi un message, mais l'animal pourra "dire" (afficher) le mot ou la phrase que nous lui fournirons. Nous passerons ce mot à la méthode dire() comme un argument de méthode. La méthode construira une phrase en utilisant cet argument et la retournera au programme appelant.

La nouvelle version de la classe AnimalFamilier ressemble à ceci :

 
Sélectionnez
public class AnimalFamilier {
  int âge;
  float poids;
  float taille;
  String couleur;
   
  public void dormir() {
    System.out.println("Bonne nuit, à demain");
  }
 
  public void manger() {
    System.out.println(
            "J'ai si faim… Donne-moi un biscuit !");
  }
 
  public String dire(String unMot) {
    String réponseAnimal = "OK !! OK !! " + unMot;
    return réponseAnimal; 
  }
}

Cette classe représente une sympathique créature du monde réel :

Image non disponible

Voyons maintenant la signature de la méthode dormir():

 
Sélectionnez
public void dormir()

Elle nous indique que cette méthode peut être appelée depuis n'importe quelle autre classe Java (public) et qu'elle ne retourne aucune donnée (void). Les parenthèses vides signifient que cette méthode ne prend pas d'argument, parce qu'elle n'a besoin d'aucune donnée du monde extérieur - elle affiche toujours le même texte.

La signature de la méthode dire() est celle-ci :

 
Sélectionnez
public String dire(String unMot)

Cette méthode peut aussi être appelée depuis n'importe quelle autre classe Java, mais elle doit retourner un texte, ce qu'indique le mot-clé String devant le nom de la méthode. Par ailleurs, elle attend une donnée textuelle de l'extérieur, d'où l'argument String unMot.

Image non disponible

Comment décider si une méthode doit retourner une valeur ou pas ? Si une méthode manipule des données et doit fournir le résultat de ces manipulations à une classe appelante, elle doit retourner une valeur. Tu vas me dire que notre classe AnimalFamilier n'a aucune classe appelante ! C'est exact, alors créons-en une, que nous appellerons MaîtreAnimal. Cette classe aura une méthode main() contenant le code nécessaire pour communiquer avec la classe AnimalFamilier. Crée simplement une autre classe nommée MaîtreAnimal, mais cette fois sélectionne dans Eclipse l'option qui crée la méthode main(). Rappelle-toi, sans cette méthode il est impossible d'exécuter cette classe en tant que programme. Modifie le code généré par Eclipse pour obtenir ceci :

 
Sélectionnez
public class MaîtreAnimal {

  public static void main(String[] args) {

    String réactionAnimal;	

    AnimalFamilier monAnimal = new AnimalFamilier();

    monAnimal.manger();
    réactionAnimal = monAnimal.dire("Cui !! Cui !!");
    System.out.println(réactionAnimal);
  
    monAnimal.dormir();
	  
  }
}

N'oublie pas d'appuyer sur Ctrl-S pour enregistrer et compiler cette classe !

Pour exécuter la classe MaîtreAnimal, sélectionne le menu Eclipse Exécuter, Exécuter…, Créer et tape le nom de la classe principale : MaîtreAnimal. Appuie sur le bouton Exécuter et le programme affichera le texte suivant :

 
Sélectionnez
J'ai si faim… Donne-moi un biscuit !
OK !! OK !! Cui !! Cui !!
Bonne nuit, à demain

La classe MaîtreAnimal est la classe appelante ; elle commence par créer une instance de l'objet AnimalFamilier. Elle déclare une variable monAnimal et utilise l'opérateur Java new :

 
Sélectionnez
AnimalFamilier monAnimal = new AnimalFamilier();

Cette ligne déclare une variable du type AnimalFamilier (c'est exact, tu peux considérer chaque classe que tu crées comme un nouveau type Java). Maintenant, la variable monAnimal sait où a été créée l'instance d'AnimalFamilier dans la mémoire de l'ordinateur, et tu peux utiliser cette variable pour appeler n'importe laquelle des méthodes de la classe AnimalFamilier, par exemple :

 
Sélectionnez
monAnimal.dormir();

Si une méthode retourne une valeur, tu dois l'appeler d'une autre façon. Déclare une variable du même type que la valeur retournée par la méthode. Tu peux maintenant appeler cette méthode :

 
Sélectionnez
String réactionAnimal;	

réactionAnimal = monAnimal.dire("Cui !! Cui !!");

A ce stade, la valeur retournée est stockée dans la variable réactionAnimal et si tu veux voir ce qu'elle contient, ne te gêne pas :

 
Sélectionnez
System.out.println(réactionAnimal);
Image non disponible

V-D. Héritage - un Poisson est aussi un AnimalFamilier

Notre classe AnimalFamilier va nous aider à découvrir un autre concept important de Java, appelé héritage. Dans la vie réelle, chaque personne hérite des caractéristiques de l'un ou l'autre de ses parents. De la même façon, dans le monde Java, tu peux, à partir d'une classe, en créer une nouvelle.

La classe AnimalFamilier possède un comportement et des attributs partagés par de nombreux animaux familiers - ils mangent, dorment, certains d'entre eux émettent des bruits, leurs peaux peuvent être de différentes couleurs, etc. D'un autre côté, les animaux familiers sont différents les uns des autres - les chiens aboient, les poissons nagent et sont silencieux, les perroquets parlent mieux que les chiens. Mais tous mangent, dorment, ont un poids et une taille. C'est pourquoi il est plus facile de créer une classe Poisson qui héritera certains comportements et attributs communs de la classe AnimalFamilier, que de créer Chien, Perroquet ou Poisson à partir de rien à chaque fois.

Le mot-clé spécial extends est là pour ça :

 
Sélectionnez
class Poisson extends AnimalFamilier {

}

On peut dire que notre Poisson est une sous-classe (subclass) de la classe AnimalFamilier et que la classe AnimalFamilier est une superclasse (superclass) de la classe Poisson. Autrement dit, on utilise la classe AnimalFamilier comme un modèle pour créer la classe Poisson.

Même si tu te contentes de laisser la classe Poisson telle qu'elle est maintenant, tu peux toujours utiliser chacun des attributs et méthodes hérités de la classe AnimalFamilier. Regarde :

 
Sélectionnez
Poisson monPetitPoisson = new Poisson();
monPetitPoisson.dormir();

Même si nous n'avons pas encore déclaré de méthode dans la classe Poisson, nous avons le droit d'appeler la méthode dormir() de sa superclasse !

Dans Eclipse, la création de sous-classes est une partie de plaisir ! Sélectionne le menu Fichier, Nouveau, Classe et tape Poisson comme nom de la classe. Remplace la valeur java.lang.Object par le mot AnimalFamilier dans le champ Superclasse.

Image non disponible

N'oublions pas cependant que nous sommes en train de créer une sous-classe d'AnimalFamilier pour ajouter certaines propriétés que seuls les poissons possèdent et réutiliser une partie du code que nous avons écrit pour un animal familier en général.

Il est temps de te révéler un secret - toutes les classes Java héritent de la super superclasse Object, que tu utilises le mot extends ou pas. Mais une classe Java ne peut pas avoir deux parents distincts. Si c'était la même chose avec les gens, les enfants ne seraient pas des sous-classes de leurs parents, mais tous les garçons seraient des descendants d'Adam et toutes les filles des descendantes d'Eve :.

Tous les animaux ne sont pas capables de plonger, mais il est certain que les poissons le peuvent. Ajoutons maintenant une nouvelle méthode plonger() à la classe Poisson.

 
Sélectionnez
public class Poisson extends AnimalFamilier {

  int profondeurCourante = 0;

  public int plonger(int combienDePlus){
    profondeurCourante = profondeurCourante + 
combienDePlus;
    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; 
  }
}

La méthode plonger() a un argument combienDePlus qui indique au poisson de combien il doit plonger. Nous avons aussi déclaré la variable de classe profondeurCourante qui enregistrera la nouvelle profondeur courante à chaque fois que tu appelleras la méthode plonger(). Cette méthode renvoie la valeur courante de la variable profondeurCourante à la classe appelante.

Crée maintenant une autre classe nommée MaîtrePoisson qui ressemble à ceci :

 
Sélectionnez
public class MaîtrePoisson {

  public static void main(String[] args) {
		
    Poisson monPoisson = new Poisson();
		
    monPoisson.plonger(2);
    monPoisson.plonger(3);
		
    monPoisson.dormir();
  }
}

La méthode main() instancie l'objet Poisson et appelle sa méthode plonger() deux fois, avec des arguments différents. Ensuite, elle appelle la méthode dormir(). Quand tu exécutes le programme MaîtrePoisson, il affiche les messages suivants :

 
Sélectionnez
Plongée de 2 mètres
Je suis à 2 mètres sous le niveau de la mer
Plongée de 3 mètres
Je suis à 5 mètres sous le niveau de la mer
Bonne nuit, à demain

As-tu noté que, outre la méthode définie dans la classe Poisson, le MaîtrePoisson appelle aussi des méthodes de sa superclasse AnimalFamilier ? C'est tout l'intérêt de l'héritage - tu n'as pas besoin de copier et coller le code de la classe AnimalFamilier - il suffit d'utiliser le mot extends et la classe Poisson peut utiliser les méthodes d'AnimalFamilier !

Image non disponible

Encore une chose : bien que la méthode plonger() renvoie la valeur de profondeurCourante, notre MaîtrePoisson ne l'utilise pas. Très bien, notre MaîtrePoisson n'a pas besoin de cette valeur ; mais peut-être y a-t-il d'autres classes qui utilisent Poisson, qui pourraient trouver cette valeur utile. Par exemple, imagine une classe ContrôleurTraficPoissons qui doit connaître les positions des autres poissons dans la mer avant d'autoriser un poisson à plonger, pour éviter les accidents :-).

V-E. Redéfinition d'une méthode

Comme tu le sais, les poissons ne parlent pas (du moins ne parlent-ils pas à voix haute). Mais notre classe Poisson hérite de la classe AnimalFamilier qui possède la méthode dire(). Ceci signifie que rien ne t'empêche d'écrire quelque chose comme ça :

 
Sélectionnez
monPoisson.dire("Un poisson qui parle !");

Eh bien, notre poisson a commencé à parler… Pour éviter que cela se produise, il faut que la classe Poisson redéfinisse (override) la méthode dire() de la classe AnimalFamilier. Voilà comment ça marche : si tu déclares une méthode avec exactement la même signature dans la sous-classe que dans la superclasse, la méthode de la sous-classe sera utilisée à la place de celle de la superclasse. Ajoutons la méthode dire() à la classe Poisson.

 
Sélectionnez
public String dire(String unMot) {
  return "Ne sais-tu pas que les poissons ne parlent pas ?";
} 

Ajoute maintenant l'appel suivant dans la méthode main() de la classe MaîtrePoisson :

 
Sélectionnez
String réactionPoisson;
réactionPoisson = monPoisson.dire("Salut");
System.out.println(réactionPoisson);

Exécute le programme et il affichera :

Ne sais-tu pas que les poissons ne parlent pas ?

Cela prouve que la méthode dire() de la classe AnimalFamilier a été redéfinie, ou, autrement dit, supprimée.

Si la signature d'une méthode inclut le mot-clé final, elle ne peut pas être redéfinie. Par exemple: final public void dormir(){…}

Waouh ! Nous en avons appris, des choses, dans ce chapitre. Que dirais-tu d'une petite pause ?

V-F. Autres lectures

V-G. Exercices

Image non disponible

1. Crée une nouvelle classe Voiture possédant les méthodes suivantes :

public void démarrer()
public void arrêter()
public int rouler(int durée)

La méthode rouler() doit renvoyer la distance totale parcourue par la voiture pendant un temps donné. Utilise la formule suivante pour calculer la distance :

distance = durée * 60;

2. Ecris une autre classe, PropriétaireVoiture, qui crée une instance de l'objet Voiture et appelle ses méthodes. Le résultat de chaque appel de méthode doit être affiché à l'aide de System.out.println().

V-H. Exercices pour les petits malins

Image non disponible

Crée une sous-classe de Voiture nommée VoitureJamesBond et redéfinis la méthode rouler(). Utilise la formule suivante pour calculer la distance :

distance = durée*180;

Sois créatif, affiche des messages amusants !


précédentsommairesuivant

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.