Skip to main content

Objet et encapsulation - Les classes

Définition : Une classe est un moule qui décrit le quoi : la spécification des messages qui peuvent être envoyés à l'objet. Et le comment la manière de réaliser cette spécification.

Pour instancier une classe, se répartit en trois formes :

  1. Classe Concrète : une classe instanciable
  2. Classe abstraite : la réalisation est incomplète, au moins une des méthodes d'instance n'a pas de mise en oeuvre (pas corps défini).
  3. Classe abstraite pure ou interface : aucune réalisation n'est définie, elle contient les déclarations des méthodes d'instance.

Ce chapitre est centré sur la construction des classes concrètes.

Classe Java

La syntaxe du langage Java différencie la construction d'une classe contenant une réalisation et d'une classe ne contenant pas de réalisation.

  1. Construction avec réalisation :
  • classe concrète avec le mot clé seul class
  • classe abstraite en ajoutant le mot-clé abstract au mot clé class
  1. Construction sans réalisation : classe abstraite pure avec le mot-clé interface. Cette construction ne contient ni attributs, ni constructeurs.

Une classe/interface Java correspond à un fichier .class obtenu après java d'un fichier source. Ce fichier (en "bytecode" ou code intermédiaire) contient le code à exécuter mais aussi les informations sur la définition de la classe, par exemple : le type des paramètres d'une méthode.

Le contenu des fichiers .class est utilisé par le compilateur (pour les informations de type) et par la machine virtuelle java (JVM) (interprétation du code intermédiaire)

Paquetage

Les paquetages permettent de regrouper les classes / interfaces par thème. Le système de paquetage est hiérarchique avec la notion de sous-paquetage. Le caractère . sert de séparateur. Les paquetages commençant par java, javax font partie de la distribution standard (JRE et JDK).

Un paquetage correspond à un domaine de nom : le nom d'une classe / interface est unique dans un paquetage. Le nom complet d'une classe / interface est constitué de la hiérarchie de paquetage puis du nom de la classe/interface. Par exemple java.lang.String. L'inclusion d'une classe/interface dans un paquetage est précisée par l'instruction package nom sur la première ligne du fichier source. Sans ce mot-clé, les classes sont incluses dans un paquetage unique sans nom (paquetage anonyme ou paquetage par défaut). Pour désigner une classe/interface à l'extérieur d'un paquetage, il est nécessaire d'utiliser son nom complet : matos.on.DentBleu maDent = new matos.onde.DentBleu();. Dans l'écriture d'un fichier source, il est possible de raccourcir le nom complet d'une classe à son nom, en utilisant le mot clé import. Au début du fichier source, l'instruction import matos.onde.DentBleu; permet de désigner la classe uniquement par DentBleu. Le compilateur lui attribue son nom complet.

Organisation physique des paquetages

L'organisation physique des fichiers .class correspond à la hiérarchie de paquetage. Le fichier String.class se trouve dans l'arborescence de répertoire java/lang. Lorsque le compilateur ou la machine virtuelle ont besoin de la définition d'une classe, ils utilisent son nom complet comme chemin de recherche du fichier .class. Par défaut, la recherche s'effectue à partir du répertoire courant (celui du lancement de la commande).

L'option -cp et la variable d'environnement CLASSPATH permettant d'indiquer les répertoires à analyser pour trouver ce chemin.

Classe concrète

La construction Java class contient trois catégories de membre : les variables, les méthodes et les constructeurs.

Portée des membres d'une classe

Les modificateurs de porte précisent la portée d'utilisation d'un membre d'une classe. Ils se placent devant chaque définition :

  1. private : accessible uniquement par la classe
  2. public : accessible partout
  3. au paquetage (pas de mot clé) : accessible par les classes du même paquetage

Une classe possède deux portées. Sans mot-clé, sa portée est restreinte à son paquetage. Avec le mot-clé public, elle est accessible à l'extrieur de son paquetage : public class DentBleu.

Définition d'une classe concrète

Définition d'une classe concrèete Java et de ses membres

[public] class NomClasse {
//Variables d'instance/attributs,
[final] [public|private] type nom [= expression];

//Méthodes d'instance,
[public | private] typeRetour méthodeInstance([liste de paramètres]) {
//code
}

//constructeurs
[public | private] NomClasse ([liste de paramètres]){
//code
}
}

Variable d'instance

  • C'est une variable locale à chaque instance. Sa valeur est stockée dans la zone mémoire de l'instance.

  • Son initialisation s'effectue soit à sa déclaration soit dans le code d'une constructeur. La machine virtuelle Java initialise systématiquement les variables d'instance avec une valeur par défaut dépendant du type (référence/null, int/0, boolean/false).

  • Le mot-clé final devant la définition d'une variable correspond à une variable constante. Son initialisation est possible dans un constructeur.

public class Telecommande{
private int nbPortes;
private final ProteCharniere[] mesPortes;
private final int NB_MAX;

public Telecommande(int capacite){
NB_MAX = capacite;
nbPortes = 0;
mesPortes = new PorteCharniere[NB_MAX];
}

public void positionner(Portecharniere p){
if(NB_MAX <= nbPortes)
return;
mesPortes[nbPortes] = p;
nbPortes++;
}
public boolean estRempli(){
return NB_MAX <= nbPortes;
}
public void activer(int numero){
mesPortes[numero].ouvrir();
}
}

Méthode d'instance

Une méthode d'instance s'applique à une instance. Il existe deux catégories de méthode :

  • méthode d'accès, ou accesseur. Elle donne des informations sur l'état des attributs.
  • méthode d'altération ou modificateur. Elle modifie l'état des attributs.

Le mécanisme de surcharge autorise plusieurs méthodes à porter le même nom. La distinction se fait, à la java, en fonction de la liste des paramètres d'appel (nombre, type et ordre). Par exemple, la méthode println de la classe java.io.PrintStream.

Le mot clé this désigne / référence l'instance qui vient de recevoir le message. Il est utilisé dans le code

  • Soit pour passer l'objet en paramètre d'une méthode (ou d'un constructeur)
  • Soit pour désigner un attribut en cas d'ambiguïté
public class Telecommande{
private int nbPortes;
private final Portecharniere[] mesPortes;

public Telecommande(int nbPortes){
this.nbPortes = 0;
this.mesPortes = new PorteCharniere[nbPortes];
}

public void positionner(PorteCharniere p){
if(this.estRempli())
return;
this.mesPortes[nbPortes]=p;
this.nbPortes++;
}
public boolean estRempli(){
return this.mesPorteS.length <= this.nbPortes;
}
public void activer(int numero){
this.mesPortes[nummero].ouvrir();
}
public void desactiver(int numero){
this.mesPortes[numero].fermer();
}
public void desactiver(){
for(int i = 0; i < this.nbPortes; i++)
if(!this.mesPortes[i].estFerme())
this.desactiver(i);
}
}
//Donner les références this à conserver ?

Exemple d'appel avec surcharge résolu à la compilation :

tele.desactiver(1);
tele.desactiver();

Constructeur

  • Un constructeur n'est pas une méthode. Il est uniquement appelé à l'instanciation. Son code assure la bonne initialisation des variables d'instance.
  • Le constructeur prendre le nom de la classe. Il n'a pas de type de retour.
  • L'instance existe au moment de l'appel du constructeur. Le code du constructeur peut utiliser les méthodes d'instance et la référence this.
  • Si une classe ne contient pas de constructeur le compilateur Java ajoute un constructeur publique sans paramètre avec un corps vide (désigné par le terme constructeur par défaut).
  • La surcharge des constructeurs est autorisée.
  • Avec la définition de plusieurs constructeurs, il est nécessaire d'avoir un mécanisme de factorisation du code d'initialisation. Un constructeur peut déclencher le code d'un autre constructeur par l'instruction (qui utilise le mécanisme de surcharge) : this(par1, par2, par3). Cette instruction doit être la première ligne du constructeur.

Lien "a-un" entre classes

Le lien "a-un" correspond à la relation d'utilisation la plus basique : la réalisation d'une encapsulation nécessite l'appel aux méthodes d'une autre encapsulation.

Relation d'utilisation dans la réalisation

La classe PorteCharniere possède un lien "a-un" avec la classe DentBleu. Une instance de PorteCharniere contient dans ses attributs la référence à une instance de DentBleu.

Dans notre cas de réalisation, l'instant de DentBleu ne peut pas être partagée et doit être utilisée dès l'instanciation de PorteCharniere.

Le lien "a-un" se traduit dans le code de la classe PorteCharniere :

  • définition d'une variable d'instance du type DentBleu
  • instanciation de DentBleu dans le constructeur et affectation à la variable d'instance

Factoriser du code

Pour éviter de dupliquer le code, la construction de la classe PorteVerrouCharniere peut se faire en utilisant un lien "a-un" avec la classe PorteCharniere. L'instanciation de la classe PorteVerrouCharniere doit instancier la classe PorteCharniere