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 :
- Classe Concrète : une classe instanciable
- 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).
- 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.
- 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
- 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 :
- private : accessible uniquement par la classe
- public : accessible partout
- 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