← (précédent) C.6 Exos de P.O.O (2)
D.0 Les interfaces graphiques
Accueil S O M M A I R E

C.7 Des classes particulières

C.7.1 La classe Object

Comme je vous l' ai déjà dit quelque part sur ce site. Il existe une classe appelée Object.

La classe Object est une classe prédéfinie. C' est la classe mère de toutes les classes. Toute classe java, prédéfinie ou non dérive forcément de la classe Object.
Exemple 1 :  

1.     class Eleve
2.     {
3.      
4.     }
5.
6.
7.     public class TesterObject
8.     {
9.          public static void main(String [] args)
10.         {
11.               Object e = new Eleve();
12.               Object s = new String();
13.         }
14.    }
Enregistrez sous : TesterObject.java

Compilez ce programme et il ne s' affichera aucun message d' erreur. Normal. Nous avons utilisé le polymorphisme. En ligne 11, nous avons créé un objet : new Eleve(). Puis nous avons mis sa référence dans une variable de type Object. Donc, d' après ce que nous avons étudié dans le chapitre Héritage et Polymorphysme, La classe Object est forcément une classe mère de Eleve.

Même explication pour la ligne 12 avec un objet de type String.

Conclusion : qu' une classe soit prédéfinie (String) ou non (Eleve), elle dérive forcément de la classe Object.
Dans ces conditions, toutes les classes héritent naturellement des champs et méthodes de la classe Object. Dans vos propres recherches, vous étudierez la classe Object. Voir cette page : class Object

Moi je vais vous parler de 2 de ces méthodes. Ce sont les méthodes qui ont un certain intérêt. Ce sont les méthodes : toString() et equals()
Exemple 2 :  Référence Object pour les objets de n' importe quelle classe.

1.     class Eleve
2.     {
3.      
4.     }
5.
6.
7.     public class TesterObject2
8.     {
9.          public static void main(String [] args)
10.         {
11.               Object e1 = new Eleve();
12.               Object e2 = new Eleve();
13.               System.out.println("e1.toString() fournit : " + e1.toString() );
14.               System.out.println("e2.toString() fournit : " + e2.toString() );
15.         }
16.    }
Enregistrez sous : TesterObject2.java

Compilez puis exécutez ce programme, il sera affiché :

e1.toString() fournit : Eleve@45a877
e2.toString() fournit : Eleve@1372a1a

La méthode toString() de la classe Object fournit une chaine de caractères composée de 2 parties. La première partie est le nom de la classe à partir de laquelle l' objet est instancié. En effet, les objets e1 et e2 sont de type Eleve. Même si leurs références respectives sont dans une variable de type Object.
La deuxième partie est la référence (l' adresse) de l' objet. Cette référence est un nombre en hexadécimal précédé du caractère @

. Naturellement, ne vous attendez pas à ce que l' adresse fournie à partir de mon PC soit la même que celle fournit à partir du votre.

Comme dans toute situation de dérivation, la classe dérivée peut redéfinir une méthode de la classe de base. Ainsi, vous pouvez redéfinir la méthode toString() pour qu' elle fournisse autre chose. Par exemple, je peut redéfinir la méthode pour qu' elle me fournisse seulement le nom de la classe. Comment ? ... Par exemple en utilisant la méthode substring() de la classe String. La méthode toString() fournit une chaine de caractères. Donc, un objet de type String. Nous pouvons donc utiliser une méthode de la classe String.
Exemple  3 :  Redéfinition de la méthode toString()

1.     class Eleve
2.     {
3.          public String toString()
4.          {
5.                String chaine = super.toString(); 
6.                int index = chaine.indexOf('@');
7.                chaine = chaine.substring(0, index);
8.                return chaine;
9.          }
10.    }
11.
12.    public class TeserObject3
13.    {
14.          public static void main(String [] args)
15.          {
16.                Object e = new Object();
17.                System.out.println("e.toString fournit : " +  e.toString() );
18.          }
19.    }

Enregistrez sous : TesterObject3.java

Compilez puis exécutez ce programme, il sera affiché :

e1.toString() fournit : Eleve

En ligne 5, j' appelle la méthode toString() de la classe de base de Eleve. C' est pourquoi j' écris super.toString(). Cette classe est forcément la classe Object, puisque dans ce programme, Eleve n' est dérivée d' aucune classe. Cette méthode renvoie une chaine de caractères que je mets dans la variable chaine. Cette chaine de caractères contient le nom de la classe Eleve, suivi de @, suivi de l' adresse de l' objet Eleve sur laquelle s' applique la méthode.

En ligne 6, je cherche la position du caractère @ dans cette chaine. Puis je mets cette position dans la variable index.
En ligne 7, je cherche la sous-chaine de chaine dont les caractères commencent par la position zéro (le premier caractère donc), et va jusqu' au caractère qui se trouve juste avant le caractère situé en position index.. Puis je mets cette sous-chaine dans la variable chaine.. Puis je retourne la variable chaine qui ne contient maintenant que la partie de la chaine qui se situe avant le caractère @. Et nous savons que cette partie est forcément le nom de la classe.

C' est pourquoi le programme affiche seulement le nom de la classe en utilisant la méthode toString() redéfinie dans la classe Eleve, dérivée de la classe Object.

Vous pouvez vous amusez à redéfinir la méthode toString() dans d' autres classes et faire en sorte qu' elle affiche exactement ce que vous voulez.
La méthode equals() de la classe Object se contente de comparer les adresse de 2 objets. Elle renvoie true si ce sont les mêmes adresses et false dans le cas contraire.
Exemple  3 :  Redéfinition de la méthode toString()

Imaginez une classe Points2.

cas 1 :

Points2 p1 = new Points2(4, 5);
Points2 p2 = new Points2(4, 5);

p1.equals(p2); fournit la valeur false.



Points2 a = new Points2(1, 3);
Points2 b = new Points2(3, 5);
a = b;

a.equals(b); fournit la valeur true.

Explications cas 1 :

Normal, on a fabriqué 2 objets distincts. Donc, forcément 2 adresses distinctes.

Explications cas 2 :

Normal ! on a pris la référence b qu' on a mis dans a. Les deux variables (a et b) ont donc la même référence. C' est pourquoi la comparaison renvoie true.
Sachez que vous pouvez aussi redéfinir la méthode equals() dans n' importe quelle classe et faire en sorte que la comparaion des objets renvoie exactement ce que vous voulez.
Exemple  4 :  Redéfinition de la méthode equals()

Supposons la méthode equals () dans la classe Points2. On aurait par exemple :

1.     public boolean equals(Points2 p)
2.     {
3.          boolean verite = false;
4.          if( this.x == p.x && this.y == p.y)
5.          {
6.               return verite;
7.          }
8.     }


Avec cette redéfinition, la comparaison des objets avec equals() renverra true si les champs des objets Points2 sont égaux. Même si les références sont différentes.

Naturellement, vous pouvez redéfinir la méthode equals() comme vous voulez.

C.7.2 Les classes (et les méthodes) déclarées avec le mot clé final

Rappel : Une variable déclarée avec le mot clé final est une constante. Donc, on ne peut plus modifier sa valeur.

Une méthode déclarée avec le mot clé final ne peut plus être redéfinie. Sauf si dans sa définition, elle fait appel à une autre méthode, non déclarée avec le mot final

Une classe déclarée avec le mot clé final ne peut plus être dérivée.

Pour vous débutants, je vous conseille vivement de ne pas utiliser une méthode finale, encore moins une classe finale. Il faut maîtriser ces notions et s' assurer que c' est indispensable avant de les utiliser.

C.7.3 Les classes abstraites

Une classe abstraite est déclarée avec le mot clé abstract. On ne peut pas instancier un objet avec cette classe. Elle ne sert qu' à dériver d' autres classes.
Exemple  5 :

1.     abstract class Mere
2.     {
3.          public void afficher()
4.          {
5.               System.out.println("Afficher ce qu' on veut");
6.          }
7.          
8.          public abstract void rendre(double k);
9.       
10.    }
11. 
12.    class Fille extends Mere
13.    {
14.          public void rendre(double k)
15.          {
16.               System.out.println("rendre la valeur double de k : " + 2*k);
17.          }
18.    }

Si dans un programme, vous écrivez Mere m; il n' y aura pas de message d' erreur. En effet, a n' est pas un objet de Mere. Mais plutôt une référence à un objet de type Mere ou de type Derive de Mere. En l' occurence, Fille.
En écrivant Mere m = new Mere(); il y aura un message d' erreur. Car on ne peut pas instancier un objet à partir d' une classe abstraite.
En écrivant Mere m = new Fille(); Il n y aura pas de message d' erreur. Parce qu' on a instancié u objet de type Fille. C' est sa référence qui se trouve dans la variable de type Mere.

Dans la classe abstraite Mere, on a défini la méthode afficher(). On peut appliquer cette méthode aux objets de la classe Fille.
Mais il y a une autre méthode dans cette classe. La méthode rendre. Elle est abstraite et surtout, elle n' est pas définie. On ne peut donc pas l' utiliser.
En revanche, on peut la redéfinir dans la classe dérivée Fille. Ce qu' on a d' ailleur fait (lignes 14 à 17).

Remarquez :

Le point-virgule qui termine la ligne 8. En général, la déclaration d' une méthode ne se termine pas par un point-virgule.
Mais ici, la méthode n' est pas définie et est seulement déclarée. Dans ces conditions, il faut terminer la déclaration par un point-virgule.
Autres choses à savoir sur les classes abstraites :

Il suffit qu' une classe possède une seule méthode abstraite pour qu' elle soit abstraite. Même si le mot clé abstract est absent dans sa déclaration.

Une méthode abstraite ne peut pas être déclarée sans le mot clé public. Et pour cause, elle est sensée être redéfinie dans des classes dérivées.

Les arguments d' une méthode abstraite sont forcément présents même s' ils ne servent à rien. Ex : public abstract void rendre(double k); Ici, l' argument k est de type double

Lorsqu' une classe dérive d' une classe abstraite, elle n' est pas obligée de redéfinir toutes ses méthodes abstraites. Elle peut même ne redéfinir aucune de ces méthodes . Dans ce cas, la classe dérivée reste abstraite.

C.7.4 Les interfaces

Sens le plus général : En POO, quelque soit le langage, une interface d' une classe, l' ensemble des méthodes publiques de cette classe. Ces méthodes peuvent être utilisées dans une autre classe. Je dirais que ces méthodes permettent à une classe d' interagir avec d' autres classes.

En java, une interface est une classe particulière n' ayant que des méthodes publiques à redéfinir. Les méthodes de cette classe ne sont que des déclarations de mathodes. Je dirais, des en-têtes de méthodes. Comme par exemple dans les classes abstraites. Regardez la ligne 8 de l' exemple 5. Une insterface possède en outre des champs. Mais ces champs ne sont que des constantes. Aucune classe ne peut dériver d' une interface. En réalité, il existe un comportement qui ressemble à la dérivation. On appelle cela l' implémentation. Cela ressemble à la dérivation parce que la classe qui implémente une interface hérite de toutes ces méthodes. Mais elle doit les redéfinir.
Autre chose : une classe peut implémenter plusieurs interfaces. On aboutit alors à la notion d' héritage multiple qu' on trouve dans le langage. Mais attention, une classe ne peut toujours pas hériter de plus d' une classe.

Voyons quelques exemples.
Exemple  6 : Déclaration et définition d' une interface.

1.     public interface Mousse
2.     {
3.          public void marcher();
4.          public int rendre (double d);
5.     }
Ligne 1 : je déclare une interface grace au mot clé interface à la place du mot class. Le nom de l' interface est Mousse.
Ligne 3 : je déclare la méthode marcher() de type void sans arguments.
Ligne 4 : je déclare la méthode rendre() de type int avec 1 argument de type double.

Les méthodes d' une interface sont abstraites même si le mot clé abstract ne s' y trouve pas. En effet, comment utiliser une méthode non définie ? On est obligé de la redéfinir.
Les méthodes d' une interface sont forcément public. Puisqu' elles sont sensées être redéfinies.
Exemple  7 : Implémentation  d' une interface.

1.     public class Nantis implements Mousse
2.     {
3.          public void marcher()
4.          {
5.                System.out.println("marcher sur mousse");
6.          }
7.  
8.          public int rendre (double d)
9.          { 
10.              System.out.println("rendre la mousse");
11.         }
12.     }
L' implémentation se présente comme la dérivation. Mais au lieu de extends, on a implements. Dans la dérivation, la classe hérite des méthodes de la classe de base. Certaines méthodes de la classe de base pouvant être redéfinies.
Alors que dans l' implémentation, toutes les méthodes de l' interface sont obligatoirement redéfinies.
Exemple  8 : Dérivation + Implémentation 

1.     public class Points21 extends Points2 implements Mousse
2.     {
3.          public void marcher()
4.          {
5.                System.out.println("marcher sur mousse");
6.          }
7.  
8.          public int rendre (double d)
9.          { 
10.              System.out.println("rendre la mousse");
11.         }
12.     }
Une classe peut dériver d' une autre et en même temps implémenter une interface. Tout se passe comme si on avait affaire à un héritage multiple. Mais ce n' est pas le cas.

Il existe d' autres choses à dire sur les interfaces. Mais c' est surtout en programmation graphique qu' on les utilise beaucoup. A ce moment, vous en apprendrez plus sur elles. RDV donc en programmation graphique.

C.7.5 Les classe internes

Une classe interne est une classe déclarée à l'intérieur d'une autre classe. Elle possède les mêmes possibilités qu'une autre classe, mais elle est dépend toujours de la classe qui la contient. Elle ne peut être utilisée que par la classe conteneur.

On distingue 4 types de classes internes :

Les classes internes statiques - Les classes internes - Les classes locales - Les classes anonymes.
Exemple  9 : Architecture 

1.     class Externe
2.     {
3.          class Interne
4.          {
11.          
12.         }
13.    }
Comme vous pouvez le voir, une classe interne est définie à l' intérieur d' une classe considérée comme externe, naturellement.
Exemple  10 : Accessibilté aux membres. 


1.     class Externe
2.     {
3.          int a = 5;
3.          class Interne
4.          {
11.           int b = a;
12.         }
13.    }
Compilez cette classe. Aucun message d' erreur ne s' affichera. En effet, contrairement aux classes qui ne sont pas internes, une classe interne peut accéder aux membres de sa classe Externe sans évoquer cette dernière. On n'aura pas besoin d' écrire Externe.a
Je ne vais pas aller plus loin. Parce que mon site est destiné aux débutants en programmation. Et vous n'en avez pas besoin. Mais vous devez savoir que ces classes existent.

Une classe interne a un intérêt particulier. Accéder aux champs et méthodes de sa classes externe, même déclarés en private.

Un autre intérêt réside dans l'héritage.

C.7.6 Les classes enveloppes

Nous avons déjà manipulé les variables de type primitif : byte, short, int, long, float, double, boolean, char.

Ces variables disposent des équivalents en forme de classes. Pourquoi ? ... ainsi, ils peuvent disposer de certaines méthodes. Les classes correspondantes sont :

byte ---> Byte
short ---> Short
int ---> Integer
long ---> Long

float ---> Float
double ---> Double

boolean ---> Boolean

char ---> Character

N' oubliez pas que le nom d' une classe commence toujours par une lettre majuscule.

Nous étudierons ces classes dans le chapitre C.11 consacré à l' étude de quelques classes prédéfinies du package Java.lang.

C.7.7 Les types énumérés

Certaines classes sont déclarées, non pas avec le mot clé class. Mais plutôt avec le mot clé enum

Au lieu de public class Numbers par exemple, on aura : public enum Numbers .

Une énuméaration en java, permet de définir un ensemble de constantes dont le type est la classe elle-même. Avant la version 5.0 de java, on pouvait déclarer une liste de constantes de cette façon
Exemple  11 : énumération de constantes 


1.     public class Constantes
2.     {
3.          public static final int nombre1 = 13;
4.          public static final int nombre2 = 55;
5.          public static final int nombre3 = 21;
6.          public static final int nombre4 = 30;
7.     }

On utilise l' un de ces constantes dans une autre classe en écrivant par exemple : Constantes.nombre1 . Mais créer des constantes de cette façon peut présenter un inconvénient.



pour la partie D, revenir à l'ancienne version D : les interfaces graphiques.
La connaissance, c'est bien. La partager, c'est mieux
Conseiller ce site à un(e) ami(e):

Son e-mail est :       
Une suggestion à faire pour ce site ? ... Contact : webmaster@debutantprog.com
← (précédent) C.6 Exos de P.O.O (2)
D.0 Les interfaces graphiques
Accueil S O M M A I R E

C.7 Des classes particulières