LECON 201


Java Orienté Objet
Dans cette partie, nous allons aborder la programmation orientée objet. Concept de programmation extrêmement puissant et pratique.
En effet, vous verrez qu'avec ce type de programmation, vous pourrez créer, utiliser, recréer divers objets et les utiliser dans un but que vous seuls aurez décidé.
J'aborderai ce que j'ai pu voir durant ma formation, et uniquement cela... Mais je vous rassure : il y a déjà du travail...

Cette partie sera extrêmement riche en concepts, vocabulaire et méthodologie. Entre autres, vous saurez programmer en orienté objet, vous pourrez enregistrer vos objets dans des fichiers...

J'ajouterai aussi quelques notions de modélisation. Ceci dans le but de vous familiariser avec la façon de schématiser des objets et leurs interactions entre eux. Nous y reviendrons, mais il s'agira de diagrammes de classes utilisés avec le langage
UML (Unified Modeling Language).

Une longue introduction ne servirait à rien... passons donc tout de suite à la première partie

Les premiers pas en "Orienté Objet"

Dans la première partie de ce tuto sur la programmation en Java, nous avons travaillé avec une seule classe.
Vous allez voir et apprendre qu'en programmation orientée objet, nous travaillerons avec plusieurs classes : en fait, autant de classes que d'objets.

Rappelez-vous de la première partie : vous avez déjà utilisé des objets...
Oui ! Lorsque vous faisiez ceci :
Code : Java
1
String str = new String("tiens... un objet String");

Ici str est un objet String. Vous avez créé un objet de la classe String : on dit que vous avez créé une instance de la classe String(). Nous savons cela grâce à l'opérateur new, qui s'utilise pour instancier une classe.
L'objet String, instancié ci-dessus, a bien ses propres données : la chaîne de caractères "tiens... un objet String". Vous devez savoir aussi que les variables de type String() (mais nous préfèrerons parler d'objet à partir de maintenant) ont des méthodes associées, comme subString().

Je vous sens quelque peu perplexes... mais néanmoins rassurés... Attaquons sans plus attendre !
Sommaire du chapitre :

  • Les classes
  • Les constructeurs
  • Votre objet sait parler : accesseurs et mutateurs
  • Travaillez avec votre objet : les méthodes
  • Les variables de classes
  • Astuce Eclipse
  • Ce qu'il faut retenir

Les classes

Une classe peut être comparée à un moule, qui, lorsque nous le remplissons, nous donne un objet ayant la forme du moule, et toutes ses caractéristiques. Comme quand vous étiez enfants, quand vous vous amusiez avec de la pâte à modeler.

Si vous avez bien suivi la première partie de ce tuto, vous devriez savoir que notre classe contenant la méthode main ressemble à ceci :

Code : Java
1
2
3
4
5
6
7
8
9
class ClasseMain{
 
public static void main(String[] args){
 
//Vos données, variables, différents traitements....
 
}// fin de la méthodes main
 
}//fin de votre classe

Créez cette classe et cette méthode main (vous savez faire, maintenant).

Puisque nous allons travailler en POO, nous allons devoir créer une seconde classe dans ce fameux projet ! Nous allons donc tout de suite créer une classe Ville.
Dans un but de simplicité, j'ai pensé que créer des objets Ville vous permettrait d'assimiler plus facilement le concept objet. Nous allons donc créer des objets Ville avant la fin de ce chapitre...

Allez dans File / New / Class ou utilisez le raccourci dans la barre d'outils, comme ceci :



Nommez votre classe : Ville (convention de nommage ! !). Mais cette fois vous ne devez pas créer la méthode main.
Il ne peut y avoir qu'une seule méthode main par projet ! Souvenez-vous que celle-ci est le point de départ de votre programme ! Et un programme ne commence qu'à un seul endroit !
Pour être tout à fait précis, il peut exister plusieurs méthode main dans votre projet (oui, même une par classe...) MAIS une seule sera considérée comme le point de départ de votre programme !

Au final, vous devriez avoir ceci :



Voilà ! Maintenant vous avez votre classe, avec la méthode main, et votre classe Ville encore vide mais qui va bientôt pouvoir créer des objets Ville.

Un dernier mot cependant. Ici, notre classe ville est précédée du mot clé "public". Vous devez savoir que lorsque nous créons une classe comme nous l'avons fait, Eclipse nous facilite la tache en mettant ce mot clé. Nous verrons plus tard qu'il existe d'autres mots clé pour définir la portée d'une classe (nous y viendrons). Si nous enlevons ce mot clé, l'interpréteur Java considèrera, tacitement, votre classe comme public.
Retenez que, par défaut et sans instructions contraires, toutes les classes sont public !

C'est-à-dire ?

Nous verrons cela à la fin du chapitre... Dès que nous aurons créé des objets !
Retenez que :

Code : Java
1
2
3
public class UneClasse{
  
}//fin de votre classe

et
Code : Java
1
2
3
class UneClasse{
  
}//fin de votre classe

Sont deux codes équivalents !

Ce mot-clé, public, vous l'avez déjà rencontré lors du chapitre sur les méthodes.
Mais lorsque public précède une méthode, il s'agit d'un droit d'accès à une méthode membre d'une classe... c'est-à-dire qu'avec le mot-clé public devant une méthode, celle-ci sera accessible par toutes les classes utilisant cette dernière. Bien entendu, nous aurons besoin de ce genre de méthode, mais nous aurons aussi besoin d'autres méthodes dont nous ne nous servirons que dans la classe où celle-ci sera créée...

Dans ce cas de figure, nous utiliserons le mot clé private. Ce qui signifie que notre méthode ne pourra être appelée que dans la classe où elle a vu le jour !
Il en va de même pour les variables. Nous allons voir, dans la deuxième sous-partie, que nous pouvons protéger des variables grâce au mot-clé private. Le principe sera le même que pour les méthodes... Ces variables ne seront accessibles que dans la classe où elles seront nées...


Bon !... Toutes les conditions sont réunies pour pouvoir commencer activement la programmation orientée objet ! Et si nous allions créer notre première ville ?

Les constructeurs

Derrière ce mot un peu barbare, se cache une notion toute bête. Vu que notre objectif dans ce chapitre est de construire un objet Ville, il va falloir définir les données qu'on va lui attribuer.

Nous dirons qu'un objet Ville a :
  • un nom sous forme de chaîne de caractères,
  • un nombre d'habitants sous la forme d'un entier,
  • un pays apparenté sous la forme d'une chaîne de caractères.

Je suis bien d'accord ! Mais comment fait-on pour dire à notre programme que notre objet a tout ça ?

Tout simplement en mettant des variables (dites d'instances) dans notre classe.
Celle-ci va contenir une variable dont le rôle sera de stocker le nom, une autre stockera le nombre d'habitants et la dernière se chargera du pays !
Voilà à quoi ressemble notre classe Ville à présent :

Code : Java
1
2
3
4
5
6
7
public class Ville{
 
  String nomVille;
  String nomPays;
  int nbreHabitant;
 
}


Rappelez-vous que, par défaut, les variables d'instances présentes dans une classe sont public.
Pourquoi tu dis variables d'instances ?

Tout simplement parce que dans nos futures classes Java, qui définiront des objets, il y aura plusieurs types de variables dans celles-ci (nous approfondirons ceci dans ce chapitre).
Pour le moment, sachez qu'il y a trois grands types de variables dans une classe objet :
  • les variables d'instances : ce sont elles qui définiront les caractéristiques de notre objet ;
  • les variables de classes : celles-ci sont communes à toutes les instances de votre classe ;
  • les variables locales : ce sont des variables que nous utiliserons pour travailler dans notre objet.


Dans l'immédiat, nous allons travailler avec des variables d'instances afin de créer des objets différents. Il nous reste plus qu'à créer notre premier objet mais pour ce faire, nous allons devoir créer ce qu'on appelle des constructeurs.

Un constructeur est une méthode (ou méthode d'instance, vu qu'elle interagit avec une instance de votre classe) qui va se charger de créer un objet et, le cas échéant, d'initialiser ses variables de classe ! Cette méthode a pour rôle de dire à la JVM de réserver de l'allocation mémoire pour notre futur objet et donc, par extension, d'en réserver pour toutes les variables d'instances et variables de classes de cette dernière !

Notre premier constructeur sera ce qu'on appelle communément un constructeur par défaut.
C'est-à-dire qu'il ne prendra aucun paramètre mais permettra tout de même d'instancier un objet et vu que nous sommes perfectionnistes, nous allons initialiser nos variables d'instances.
Voici votre premier constructeur :

Code : Java
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
public class Ville{
   /**
   * Stocke le nom de notre ville
   */
  String nomVille;
  /**
   * Stocke le nom du pays de notre ville
   */
  String nomPays;
  /**
   * Stocke le nombre d'habitants de notre ville
   */
  int nbreHabitant;
 
  
  /**
   * Constructeur par défaut
   */
  public Ville(){
      System.out.println("Création d'une ville !");      
      nomVille = "Inconnu";
      nomPays = "Inconnu";
      nbreHabitant = 0;
  }
 
}


Vous avez remarqué que le constructeur est en fait une méthode qui n'a aucun type de retour (void, double...) et qui porte le même nom que notre classe !
Ceci est une règle immuable : le (les) constructeur(s) d'une classe doit (doivent) porter le même nom que la classe !

Une classe peut avoir plusieurs constructeurs ?

Bien sûr !
Il s'agit de la même méthode, mais surchargée ! Dans notre premier constructeur nous n'avons passé aucun paramètre, mais nous allons bientôt en mettre.

Vous pouvez d'ores et déjà créer une instance de ville.
Mais tout d'abord, rappelez-vous qu'une instance d'objet se fait grâce au mot-clé new. Comme lorsque vous créez une variable de type String. Vous avez sûrement déjà dû faire ce genre de déclaration :

Code : Java
1
String mot = new String();


Maintenant, vu que nous allons créer des objets Ville, nous allons procéder comme pour les String.

Vérifions que l'instanciation se fait bien. Allez dans votre classe contenant la méthode main et instancions un objet Ville. Je suppose que vous avez deviné que le type de notre objet ne sera pas double, int ou long mais bien Ville !

Code : Java
1
2
3
4
5
6
7
8
9
public class Sdz1{
 
 public static void main(String[] args){
   
     Ville ville = new Ville();
 
 }
 
}


Exécutez ce code, et voilà !


Félicitations ! Vous avez créé votre premier objet ! !

Je sais bien que, pour le moment, il ne sert à rien...
Mais vous devez passer par là afin de comprendre le principe de la POO.

Maintenant, nous devons mettre des données dans notre objet, ceci afin de pouvoir commencer à travailler...
Le but final serait d'avoir une déclaration d'objet se faisant comme ceci :

Code : Java  
1
Ville ville1 = new Ville("Marseille", 123456789, "France");



Vous avez remarqué qu'ici les paramètres sont renseignés : eh bien il suffit de faire une méthode qui récupère ces paramètres, et initialise les variables de notre objet. Notre constructeur d'initialisation sera créé.

Voici le constructeur de notre objet ville, celui qui permet d'avoir des objets avec des paramètres différents. Comme je suis sympa, voici toute la classe telle qu'elle est maintenant :

Code : Java
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
public class Ville {
 
  /**
   * Stocke le nom de notre ville
   */
  String nomVille;
  /**
   * Stocke le nom du pays de notre ville
   */
  String nomPays;
  /**
   * Stocke le nombre d'habitants de notre ville
   */
  int nbreHabitant;
 
  
  /**
   * Constructeur par défaut
   */
  public Ville(){
          System.out.println("Création d'une ville !");          
          nomVille = "Inconnu";
          nomPays = "Inconnu";
          nbreHabitant = 0;
  }
 
  /**
   * Constructeur d'initialisation
   * @param pNom 
   *                    Nom de la Ville
   *  @param pNbre
   *                    Nombre d'habitants
   *  @param pPays
   *                    Nom du pays
   */
  public Ville(String pNom, int pNbre, String pPays)
  {
          System.out.println("Création d'une ville avec des paramètres !");     
          nomVille = pNom;
          nomPays = pPays;
          nbreHabitant = pNbre;
  }
        
}


Dans ce cas, l'exemple de déclaration et d'initialisation d'un objet ville que je vous ai montré un peu plus haut fonctionne sans aucun souci ! MAIS il vous faudra respecter scrupuleusement l'ordre des paramètres passés lors de l'initialisation de votre objet, sinon, c'est l'erreur de compilation à coup sûr !
Ainsi :
Code : Java
1
2
Ville ville1 = new Ville("marseille", 123456789, "France");//l'ordre est respecté => aucun souci
Ville ville2 = new Ville(12456, "France", "Lille");//Erreur dans l'ordre des paramètres => erreur de compilation au final


Testez ce code dans votre méthode main :
Code : Java
1
2
Ville ville =  new Ville();
Ville ville2 = new Ville("Marseille", 123456789, "France");


Voici le résultat :



Vous venez de surcharger le constructeur !


Par contre, notre objet à un gros défaut...
Les variables d'instances qui le caractérisent sont accessibles dans votre classe contenant votre main !

Ceci veut dire que vous pouvez modifier les attributs d'une classe directement. Testez ce code et vous verrez :
Code : Java  
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
public class Sdz1 {
 
        public static void main(String[] args)
        {
                Ville ville =  new Ville();
                System.out.println(ville.nomVille);
                ville.nomVille = "la tête à toto ! ! ! !";
                System.out.println(ville.nomVille);
                
                Ville ville2 = new Ville("Marseille", 123456789, "France");
                ville2.nomPays = "La tête à tutu ! ! ! ! ";
                System.out.println(ville2.nomPays);
        }
          
}

Et le résultat :




Vous voyez que nous pouvons accéder aux variables d'instances en utilisant le ".". Comme lorsque vous appelez la méthode subString() de l'objet String.
C'est très risqué et la plupart des programmeurs Java vous le diront.
Pour la plupart des cas, nous allons contrôler les modifications des variables de classe de manière à ce qu'un code ne fasse pas n'importe quoi avec nos objets !

C'est pour cela que nous protégeons nos variables d'instances en les déclarant private. Comme ceci :
Code : Java 
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
public class Ville {
 
  /**
   * Stocke le nom de notre ville
   */
  private String nomVille;
  /**
   * Stocke le nom du pays de notre ville
   */
  private String nomPays;
  /**
   * Stocke le nombre d'habitants de notre ville
   */
  private int nbreHabitant;
 
  
  /**
   * Constructeur par défaut
   */
  public Ville(){
          System.out.println("Création d'une ville !");          
          nomVille = "Inconnu";
          nomPays = "Inconnu";
          nbreHabitant = 0;
  }
 
  /**
   * Constructeur d'initialisation
   * @param pNom 
   *                    Nom de la Ville
   *  @param pNbre
   *                    Nombre d'habitants
   *  @param pPays
   *                    Nom du pays
   */
  public Ville(String pNom, int pNbre, String pPays)
  {
          System.out.println("Création d'une ville avec des paramètres !");     
          nomVille = pNom;
          nomPays = pPays;
          nbreHabitant = pNbre;
  }
        
}

Et, si vous n'avez pas effacé les lignes de code où nous avons modifié les attributs de nos objets Ville, vous devez voir qu'Eclipse n'apprécie pas du tout que vous tentiez d'accéder à des variables de classe privé !
Ces attributs ne sont plus accessibles en dehors de la classe où ils sont déclarés !


À partir de maintenant, ce ne sera plus le programme instanciant une classe qui ira voir ou modifier les attributs de notre objet, mais notre objet qui renverra les informations (ou les modifiera) lorsque le programme lui demandera !

Bon... Vous avez fait le plus dur ! Si, si, je vous assure ! :p

Maintenant, il va falloir se servir de ces objets... Eh oui ! Le but est tout de même d'utiliser nos objets dans des programmes.
Pour pouvoir accéder aux données de nos objets, nous allons utiliser ce que l'on appelle des ACCESSEURS et pour modifier les données, on appelle ça des MUTATEURS. Donc que dire, si ce n'est :
"À l'abordage, moussaillons ! "

Votre objet sait parler : accesseurs et mutateurs

Un accesseur est une méthode qui va nous permettre d'accéder aux variables de nos objets en lecture et un mutateur, en écriture !


Reprenons là où nous nous étions arrêtés.

Vous avez une classe Ville qui crée vos objets.
Vous avez une classe avec une méthode main, prête à accueillir vos objets, et tout ce que vous voudrez en faire ! Mais voilà... pas moyen de faire quelque chose de ces satanés objets ! Eh bien... le calvaire est presque terminé ! Grâce aux accesseurs, vous pourrez afficher les variables de vos objets, et grâce aux mutateurs, les modifier.

Voilà à quoi ressemblent les accesseurs et les mutateurs :

Code : Java 
public class Ville {
 
  /**
   * Stocke le nom de notre ville
   */
  private String nomVille;
  /**
   * Stocke le nom du pays de notre ville
   */
  private String nomPays;
  /**
   * Stocke le nombre d'habitants de notre ville
   */
  private int nbreHabitant;
 
  
  /**
   * Constructeur par défaut
   */
  public Ville(){
          System.out.println("Création d'une ville !");          
          nomVille = "Inconnu";
          nomPays = "Inconnu";
          nbreHabitant = 0;
  }
 
  /**
   * Constructeur d'initialisation
   * @param pNom 
   *                    Nom de la Ville
   *  @param pNbre
   *                    Nombre d'habitants
   *  @param pPays
   *                    Nom du pays
   */
  public Ville(String pNom, int pNbre, String pPays)
  {
          System.out.println("Création d'une ville avec des paramètres !");     
          nomVille = pNom;
          nomPays = pPays;
          nbreHabitant = pNbre;
  }
        
  
  //*****************************************************************************************
  //                                    ACCESSEURS
  //*****************************************************************************************
  
  /**
   * Retourne le nom de la ville
   * @return le nom de la ville
   */
  public String getNom()
  {
          return nomVille;
  }
  
  /**
   * Retourne le nom du pays
   * @return le nom du pays
   */
  public String getNomPays()
  {
          return nomPays;
  }
  
  /**
   * Retourne le nombre d'habitants
   * @return nombre d'habitants
   */
 public int getNombreHabitant()
 {
         return nbreHabitant;
 }
 
 
 //*****************************************************************************************
 //                                    MUTATEURS
 //*****************************************************************************************
 
 /**
  * Définit le nom de la ville
  * @param pNom
  *             nom de la ville
  */
 public void setNom(String pNom)
 {
          nomVille = pNom;
 }
 
 /**
  * Définit le nom du pays
  * @param pPays
  *             nom du pays
  */
 public void setNomPays(String pPays)
 {
          nomPays = pPays;
 }
 
 /**
  * Définit le nombre d'habitants
  * @param nbre
  *             nombre d'habitants
  */
public void setNombreHabitant(int nbre)
{
         nbreHabitant = nbre;
}
  
}


Nos accesseurs sont bien des méthodes, et elles sont public pour que vous puissiez y accéder dans une autre classe que celle-ci (la classe main, par exemple.. :-°).

Les accesseurs sont du même type que la variable qu'ils doivent retourner. Ça semble logique, non ? :p
Les mutateurs sont, par contre, de type void. Ce mot clé signifie "rien" ; en effet, ces méthodes ne retournent aucune valeur, elles se contentent de les mettre à jour.
Je vous ai fait faire la différence entre accesseurs et mutateurs mais, généralement, lorsqu'on parle d'accesseurs, ce terme englobe aussi les mutateurs.
Autre chose : il s'agit ici d'une question de convention de nommage. Les accesseurs commencent par get et les mutateurs par set, comme vous pouvez le voir ici. On parle d'ailleurs de Getters et de Setters.


Essayez ce code dans votre méthode main :

Code : Java -
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
Ville v = new Ville();
        Ville v1 = new Ville("marseille", 123456, "france");       
        Ville v2 = new Ville("rio", 321654, "brésil");
        
        
        System.out.println("\n v = "+v.getNom()+" ville de  "+v.getNombreHabitant()+ " habitants se situant en "+v.getNomPays());
        System.out.println(" v1 = "+v1.getNom()+" ville de  "+v1.getNombreHabitant()+ " habitants se situant en "+v1.getNomPays());
        System.out.println(" v2 = "+v2.getNom()+" ville de  "+v2.getNombreHabitant()+ " habitants se situant en "+v2.getNomPays()+"\n\n");
        
        /*Nous allons interchanger les Villes v1 et v2
        tout ça par l'intermédiaire d'un autre objet Ville        
        */
       
       Ville temp = new Ville();
       temp = v1;
       v1 = v2;
       v2 = temp;
       
       System.out.println(" v1 = "+v1.getNom()+" ville de  "+v1.getNombreHabitant()+ " habitants se situant en "+v1.getNomPays());
       System.out.println(" v2 = "+v2.getNom()+" ville de  "+v2.getNombreHabitant()+ " habitants se situant en "+v2.getNomPays()+"\n\n");
       
       /*nous allons maintenant interchanger leurs noms
       cette fois par le biais de leur accesseurs
       */
      
      v1.setNom("Hong Kong");
      v2.setNom("Djibouti");
      
      System.out.println(" v1 = "+v1.getNom()+" ville de  "+v1.getNombreHabitant()+ " habitants se situant en "+v1.getNomPays());
      System.out.println(" v2 = "+v2.getNom()+" ville de  "+v2.getNombreHabitant()+ " habitants se situant en "+v2.getNomPays()+"\n\n");


À la compilation, vous devriez obtenir ceci :

Vous voyez bien que les constructeurs ont fonctionné, que les accesseurs tournent à merveille, et que vous pouvez commencer à travailler avec vos objets Ville.
Mais la gymnastique des doigts à effectuer pour afficher les caractéristiques de nos objets... pfiou !... T'aurais pu faire plus simple ! Si seulement notre objet pouvait faire ça tout seul...

Il peut le faire !
Qu'est-ce qu'on attend ? Ben rien... on y va !

Travaillez avec votre objet : les méthodes

Bon, alors là... c'est une formalité ! Vous savez quasiment tout.
Mais attends... tu vas nous reparler des méthodes, alors que tu ne fais que ça depuis le début de ce chapitre ?

Eh bien oui ! Ceci fait partie de la méthodologie que l'on m'a enseignée en formation, même si tout ce que nous avons fait depuis le début se rapporte aux méthodes, il faut différencier :
  • les constructeurs => méthodes servant à créer des objets
  • les accesseurs => méthodes servant à accéder aux données de nos objets
  • et les méthodes de classe => méthodes servant à la gestion de nos objets.

Les méthodes de classe vont vous permettre de gérer, éditer, afficher... faire tout ce que vous voudrez avec vos objets.
Il ne vous reste plus qu'à trouver des méthodes qui fassent quelque chose pour vos objets...

Avec nos objets ville, nous sommes un peu limités en choix de méthodes... Mais nous pouvons tout de même en faire une ou deux pour l'exemple :
  • faire un système de catégories de villes par rapport à leur nombre d'habitants ( <1000 => A, <10 000 => B...). Ceci déterminé à la construction ou à la redéfinition du nombre d'habitants, donc ajouter une variable d'instance de type char à notre classe, appelons-la categorie. Penser à ajouter le traitement aux bons endroits.
  • faire une méthode de description de notre objet Ville
  • une méthode pour comparer deux objets par rapport à leur nombre d'habitants.

Nous voulons que la classe Ville gère la façon de déterminer la catégorie elle-même et non que cette action puisse être opérée de l'extérieur. La méthode qui fera ceci sera donc déclarée private.


Par contre, un problème va se poser ! Vous savez déjà qu'en Java on appelle des méthodes grâce à notre variable qui nous sert de référence, celle-ci suivie de l'opérateur ".", puis du nom de la dite méthode.
Par exemple :

Code : Java
1
2
String str = new String("opizrgpinbzegip");
str = str.subString(0,4);

Comment fait-on référence aux données de notre objet dans notre classe ?

En fait, c'est tout simple ! Encore un mot clé à retenir... Cette fois, il s'agit du mot-clé this.
Voici tout d'abord le code de notre class Ville en entier, c'est-à-dire avec nos méthodes associées :

Code : Java
public class Ville {
 
  /**
   * Stocke le nom de notre ville
   */
  private String nomVille;
  /**
   * Stocke le nom du pays de notre ville
   */
  private String nomPays;
  /**
   * Stocke le nombre d'habitants de notre ville
   */
  private int nbreHabitant;
  /**
   * Stocke le type de notre ville
   */
  private char categorie;
  
  /**
   * Constructeur par défaut
   */
  public Ville(){
          nomVille = "Inconnu";
          nomPays = "Inconnu";
          nbreHabitant = 0;
          this.setCategorie();
  }
 
  /**
   * Constructeur d'initialisation
   * @param pNom 
   *                    Nom de la Ville
   *  @param pNbre
   *                    Nombre d'habitants
   *  @param pPays
   *                    Nom du pays
   */
  public Ville(String pNom, int pNbre, String pPays)
  {  
          nomVille = pNom;
          nomPays = pPays;
          nbreHabitant = pNbre;
          this.setCategorie();
  }
        
  
  //*****************************************************************************************
  //                                    ACCESSEURS
  //*****************************************************************************************
  
  /**
   * Retourne le nom de la ville
   * @return le nom de la ville
   */
  public String getNom()
  {
          return nomVille;
  }
  
  /**
   * Retourne le nom du pays
   * @return le nom du pays
   */
  public String getNomPays()
  {
          return nomPays;
  }
  
  /**
   * Retourne le nombre d'habitants
   * @return nombre d'habitants
   */
 public int getNombreHabitant()
 {
         return nbreHabitant;
 }
 
 /**
  * Retourne la catégorie de la ville
  * @return catégorie de la ville  
  */
 public char getCategorie()
 {
         return categorie;
 }
 
 //*****************************************************************************************
 //                                    MUTATEURS
 //*****************************************************************************************
 
 /**
  * Définit le nom de la ville
  * @param pNom
  *             nom de la ville
  */
 public void setNom(String pNom)
 {
          nomVille = pNom;
 }
 
 /**
  * Définit le nom du pays
  * @param pPays
  *             nom du pays
  */
 public void setNomPays(String pPays)
 {
          nomPays = pPays;
 }
 
 /**
  * Définit le nombre d'habitants
  * @param nbre
  *             nombre d'habitants
  */
public void setNombreHabitant(int nbre)
{
         nbreHabitant = nbre;
         this.setCategorie();
}
 
 
 
//*****************************************************************************************
//                                    METHODES DE CLASSE
//*****************************************************************************************
 
 
 
  /**
   * Définit la catégorie de la ville
   */
  private void setCategorie() {
 
      int bornesSuperieures[] = {0, 1000, 10000, 100000, 500000, 1000000, 5000000, 10000000};
        char categories[] = {'?', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H'};
 
        int i = 0;
        while (i < bornesSuperieures.length && this.nbreHabitant >= bornesSuperieures[i])
                i++;
 
        this.categorie = categories[i];
 
 
  }
 
  /**
   * Retourne la description de la ville
   * @return description ville
   */
  public String decrisToi(){
      return "\t"+this.nomVille+" est une ville de "+this.nomPays+", elle comporte : "+this.nbreHabitant+
              " => elle est donc de catégorie : "+this.categorie;
  }
 
  /**
   * Retourne une chaîne de caractères selon le résultat de la comparaison
   * @param v1
   *            objet Ville
   * @return comparaison de deux ville
   */
  public String comparer(Ville v1){
      String str = new String();
     
      if (v1.getNombreHabitant() > this.nbreHabitant)
          str = v1.getNom()+" est une ville plus peuplée que "+this.nomVille;
     
      else
          str = this.nomVille+" est une ville plus peuplée que "+v1.getNom();
     
      return str;
     
  }
  
}

Pour simplifier, this fait référence à l'objet courant !


Pour expliciter le fonctionnement du mot clé this, prenons l'exemple de la méthode comparer(Ville V1).
La méthode va s'appeler comme suit :
Code : Java  
1
2
3
4
Ville V = new Ville("lyon", 654, "france");
Ville V2 = new Ville("lille", 123, "france");
 
V.comparer(V2);


Dans cette méthode, nous voulons comparer les nombres d'habitants des deux objets ville. Pour accéder à la variable nbreHabitant de l'objet V2, il suffit d'utiliser la syntaxe V2.getNombreHabitant() ; nous ferons donc référence à la propriété nbreHabitant de l'objet V2.
Mais l'objet V, lui, est l'objet appelant de cette méthode. Pour se servir de ses variables, on utilise alors this.nbreHabitant, ce qui a pour effet de faire appel à la variable nbreHabitant de l'objet appelant la méthode comparer(Ville V).

Explicitons un peu ces trois méthodes.

La méthode

setCategorie()
Elle ne prend aucun paramètre, et ne renvoie rien : elle se contente de mettre à jour la variable de classe categorie. Elle regarde, par rapport au nombre d'habitants de l'objet appelant, utilisé grâce au mot clé this, dans quelle tranche se trouve la ville en question. Selon le nombre d'habitants, le caractère renvoyé changera. Nous l'appelons lorsque nous construisons un objet Ville avec ou sans paramètre, mais aussi lorsque nous redéfinissons le nombre d'habitants : de cette manière, la catégorie est mise à jour automatiquement, sans faire appel à la méthode.
Vous constaterez aussi que nous n'avons pas créé de mutateur pour la variable d'instance categorie : nous avons en effet décidé que c'est à l'objet de gérer cette variable !

La méthode

decrisToi()
Celle-ci nous renvoie un objet de type String. Elle fait référence aux variables qui composent l'objet appelant la méthode, toujours grâce à this, et nous renvoie donc une chaîne de caractères qui nous décrit l'objet, en énumérant ses composants.

La méthode

comparer(Ville V1)
Elle prend une ville en paramètre, pour pouvoir comparer les variables nbreHabitant de l'objet appelant la méthode, et de celui passé en paramètre pour nous dire laquelle est la plus peuplée !
Bien entendu, vous pouvez créer vos propres méthodes, avec leurs paramètres, leurs types, etc. Je ne vous oblige en rien à faire exactement les mêmes que moi...


Les choses doivent vous sembler plus claires...
Si nous faisions un petit test... Essayez le code suivant dans votre méthode main :

Code : Java
1
2
3
4
5
6
7
8
Ville v = new Ville();
Ville v1 = new Ville("marseille", 1236, "france");       
Ville v2 = new Ville("rio", 321654, "brésil");
        
System.out.println("\n\n"+v1.decrisToi());
System.out.println(v.decrisToi());
System.out.println(v2.decrisToi()+"\n\n");
System.out.println(v1.comparer(v2));


Ce qui devrait vous donner :





Je viens d'avoir une idée ! Et si nous essayons de savoir combien de villes nous avons créé ?
Comment faire ?
Avec une variable de classe !

Les variables de classes

Comme je vous le disais au début de ce chapitre, il y a plusieurs types de variables dans une classe.
Nous avons vu les variables d'instances qui forment la carte d'identité d'un objet et maintenant, voici les variables de classes.

Celles-ci peuvent être très pratiques. Dans notre exemple, nous allons pouvoir compter le nombre d'instances de notre classe Ville, mais vous pouvez en utiliser pour d'autres choses (un taux de TVA dans une classe qui calcule le prix TTC, par exemple).

La particularité de ce type de variable, c'est qu'elles seront communes à toutes les instances de la classe !

Créons sans plus attendre notre compteur d'instance. Il s'agira d'une variable de type int que nous appellerons nbreInstance ; celle-ci sera public et nous ferons aussi son homologue en private : appellons-la nbreInstanceBis (un accesseur sera nécessaire pour accéder à cette dernière).
Pour qu'une variable soit une variable de classe, elle doit être précédée du mot clé static. Ce qui nous donnerait dans notre classe Ville :

Code : Java
public class Ville {
 
  /**
   * Variables publiques qui comptent les instances
   */
  public static int nbreInstance = 0;
  /**
   * Variable privée qui comptera aussi les instances
   */
  private static int nbreInstanceBis = 0;
        
  /**
   * Stocke le nom de notre ville
   */
  private String nomVille;
  /**
   * Stocke le nom du pays de notre ville
   */
  private String nomPays;
  /**
   * Stocke le nombre d'habitants de notre ville
   */
  private int nbreHabitant;
  /**
   * Stocke le type de notre ville
   */
  private char categorie;
  
  /**
   * Constructeur par défaut
   */
  public Ville(){
          //On incrémente nos variables à chaque appel aux constructeurs
          nbreInstance++;
          nbreInstanceBis++;
          
          nomVille = "Inconnu";
          nomPays = "Inconnu";
          nbreHabitant = 0;
          this.setCategorie();
  }
 
  /**
   * Constructeur d'initialisation
   * @param pNom 
   *                    Nom de la Ville
   *  @param pNbre
   *                    Nombre d'habitants
   *  @param pPays
   *                    Nom du pays
   */
  public Ville(String pNom, int pNbre, String pPays)
  {  
        //On incrémente nos variables à chaque appel aux constructeurs
          nbreInstance++;
          nbreInstanceBis++;
          
          nomVille = pNom;
          nomPays = pPays;
          nbreHabitant = pNbre;
          this.setCategorie();
  }
        
  
  //*****************************************************************************************
  //                                    ACCESSEURS
  //*****************************************************************************************
  
  public static int getNombreInstanceBis()
  {
          return nbreInstanceBis;
  }
  
  /**
   * Retourne le nom de la ville
   * @return le nom de la ville
   */
  public String getNom()
  {
          return nomVille;
  }
  
  /**
   * Retourne le nom du pays
   * @return le nom du pays
   */
  public String getNomPays()
  {
          return nomPays;
  }
  
  /**
   * Retourne le nombre d'habitants
   * @return nombre d'habitants
   */
 public int getNombreHabitant()
 {
         return nbreHabitant;
 }
 
 /**
  * Retourne la catégorie de la ville
  * @return catégorie de la ville  
  */
 public char getCategorie()
 {
         return categorie;
 }
 
 //*****************************************************************************************
 //                                    MUTATEURS
 //*****************************************************************************************
 
 /**
  * Définit le nom de la ville
  * @param pNom
  *             nom de la ville
  */
 public void setNom(String pNom)
 {
          nomVille = pNom;
 }
 
 /**
  * Définit le nom du pays
  * @param pPays
  *             nom du pays
  */
 public void setNomPays(String pPays)
 {
          nomPays = pPays;
 }
 
 /**
  * Définit le nombre d'habitants
  * @param nbre
  *             nombre d'habitants
  */
public void setNombreHabitant(int nbre)
{
         nbreHabitant = nbre;
         this.setCategorie();
}
 
 
 
//*****************************************************************************************
//                                    METHODES DE CLASSE
//*****************************************************************************************
 
 
 
  /**
   * Définit la catégorie de la ville
   */
  private void setCategorie() {
 
      
      int bornesSuperieures[] = {0, 1000, 10000, 100000, 500000, 1000000, 5000000, 10000000};
        char categories[] = {'?', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H'};
 
        int i = 0;
        while (i < bornesSuperieures.length && this.nbreHabitant >= bornesSuperieures[i])
                i++;
 
        this.categorie = categories[i];
 
 
  }
 
  /**
   * Retourne la description de la ville
   * @return description ville
   */
  public String decrisToi(){
      return "\t"+this.nomVille+" est une ville de "+this.nomPays+", elle comporte : "+this.nbreHabitant+
              " => elle est donc de catégorie : "+this.categorie;
  }
 
  /**
   * Retourne une chaîne de caractères selon le résultat de la comparaison
   * @param v1
   *            objet Ville
   * @return comparaison de deux ville
   */
  public String comparer(Ville v1){
      String str = new String();
     
      if (v1.getNombreHabitant() > this.nbreHabitant)
          str = v1.getNom()+" est une ville plus peuplée que "+this.nomVille;
     
      else
          str = this.nomVille+" est une ville plus peuplée que "+v1.getNom();
     
      return str;
     
  }
 
}


Vous avez dû remarquer que l'accesseur de notre variable de classe déclarée privée est aussi déclaré static, et ceci est une règle !
Toutes les méthodes de classes n'utilisant que des variables de classes doivent être déclarées static ! On les appelle des méthodes de classes car elles sont globales à toutes vos instances !
Par contre ceci n'est plus vrai si une méthode utilise des variables d'instances et des variables de classes...


Et maintenant, si vous testez le code suivant, vous allez voir l'utilité des variables des classes :
Code : Java
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
Ville v = new Ville();
                
System.out.println("Le nombre d'instances de la classe Ville est : " + Ville.nbreInstance);
System.out.println("Le nombre d'instances de la classe Ville est : " + Ville.getNombreInstanceBis());
                        
Ville v1 = new Ville("marseille", 1236, "france");
        
System.out.println("Le nombre d'instances de la classe Ville est : " + Ville.nbreInstance);
System.out.println("Le nombre d'instances de la classe Ville est : " + Ville.getNombreInstanceBis());
                
Ville v2 = new Ville("rio", 321654, "brésil");
        
System.out.println("Le nombre d'instances de la classe Ville est : " + Ville.nbreInstance);
System.out.println("Le nombre d'instances de la classe Ville est : " + Ville.getNombreInstanceBis());


Résultat :




Vous voyez que le nombre augmente à chaque instanciation ! Et je suppose que le fait que j'ai utilisé le nom de classe Ville pour l'appel à nos variables de classes a dû vous surprendre.
Mais vous deviez savoir ceci...
Il vous faut savoir aussi que vous auriez également utilisé n'importe quelle instance pour faire ces appels. Vous auriez eu le même résultat - peu importe l'instance choisie - car cette donnée ne dépend pas de l'instance, mais de la classe elle-même.


Avant la fin de chapitre, j'ai une révélation à vous faire...

Astuce Eclipse

Voici une astuce qui, je pense, va vous simplifier la vie et quelques minutes de codage...
Je vous vois déjà en train de vous imaginer coder une classe magnifique avec une centaine de variables d'instances ainsi qu'une dizaine de variables de classes, et d'un seul coup...
BOUM ! !
Vous tombez à la renverse lorsque vous devez faire tous les accesseurs de cette fabuleuse classe !

Voici quelque chose qui va vous plaire.
Eclipse vous fait les accesseurs automatiquement !

Bon : il faut tout de même créer toutes les variables au préalable, mais bon...

Nous allons prendre notre classe comme exemple.
Conservez toutes les déclarations de variables d'instances et de classes, et effacez tous les accesseurs (mutateurs compris).

Ensuite, rendez-vous dans le menu Source et choisissez l'option Generate Getters and Setters. Eclipse vous propose alors la liste des variables présentes dans la classe Ville.

Ici, j'ai coché ce qui m'intéressait et j'ai ensuite cliqué sur OK. Mes accesseurs sont tout prêts !
Alors, j'suis gentil, non ?
Comme vous pouvez le constater, Eclipse génère des accesseurs différents de ceux que nous avions faits aux préalable... Pensez-donc à mettre à jour votre méthode main si vous voulez faire des tests...

Je profite de cet intermède Eclipse pour vous expliquer pourquoi j'ai mis autant de commentaires autour de mes variables et de mes méthodes.
Par contre, ceci concerne les personnes qui ont téléchargé le JDK lors de la première partie !
Comme je l'ai mentionné dans la première partie, il y a une troisième syntaxe de commentaires et vous venez de la voir tout au long de ce chapitre. Il s'agit de commentaires javadoc !
Cette syntaxe est quasi identique aux commentaires multilignes à une différence près : la présence d'une deuxième * au début du commentaire.
Vous avez dû constater que la couleur du commentaire était différente.
  • Commentaire standard : commentaire de couleur verte.
  • Commentaire javadoc : commentaire de couleur bleue.
À quoi ça sert ?
Tout simplement à documenter vos programmes et surtout à pouvoir générer une documentation automatiquement. Dans Eclipse, il vous suffit d'aller dans Project et de cliquer sur Generate Javadoc.
Vous devez avoir une popup comme ceci :



Si la commande Javadoc n'est pas renseignée, il vous faut aller chercher, dans le répertoire bin de votre JDK, le fichier javadoc.exe (comme sur la capture d'écran, chez moi c'est dans C:\SUN\SDK\jdk\bin\javadoc.exe).
Il ne vous reste plus qu'à cliquer sur Finish et à tout approuver.

Vous avez maintenant, dans votre dossier de code source, un dossier doc, où se trouve toute la javadoc de votre projet. Double cliquez sur index.html dans ce dossier, et voilà !

Pour les personnes ayant essayé la compilation en ligne de commande, il vous suffit d'aller dans votre dossier de source Java (là où se trouvent vos fichier .java) et de taper la commande :
Code : Bash
1
javadoc Ville.java

Ce qu'il faut retenir

Après tout ceci, un petit topo ne fera pas de mal...
  • Une classe permet de définir des objets. Ceux-ci ont des attributs (variable(s) d'instances) et des méthodes (méthodes de classes + accesseurs).
  • Les objets permettent d'encapsuler du code et des données.
  • Une classe, par défaut, est déclarée public.
  • Le ou les constructeurs d'une classe doivent porter le même nom que la classe, et pas de type de retour !
  • Il est recommandé de déclarer ses variables d'instance private.
  • Dans une classe, on accède aux variables de celle-ci grâce au mot clé this.
  • Une variable de classe est une variable devant être déclarée static.
  • Les méthodes n'utilisant que des variables de classes doivent elles aussi être déclarées static.
  • On instancie un nouvel objet grâce au mot clé new.
  • L'ordre des paramètres passé dans le constructeur doit être respecté.
  • Eclipse vous aide à développer vos applications.


Voilà ! Vous venez d'apercevoir les méandres de la programmation orientée objet...
Je suis conscient que ce chapitre fut très riche en nouveautés, vocabulaire, concepts et méthodologie... mais n'est-ce pas ce que je vous avait dit ?


Vous venez de voir l'un des chapitres les plus conséquents de cette partie...
Normalement, vous pouvez désormais créer et gérer des objets... Mais... (parce qu'il y a un mais)... vous allez voir, au fil de la partie suivante, que la programmation orientée objet offre tout un éventail de possibilités. L'une des plus importantes n'est autre que la notion d'héritage.

Sans perdre une seconde, je propose à ceux qui se sentent d'attaque de passer à la suite !


0 comments to "LECON 201"

Post a Comment

About This Blog

Aller au debut de la page