Vous êtes sur la page 1sur 36

UEF4.3.

PROGRAMMATION
ORIENTÉE OBJET

Mme SADEG & Mme BOUSBIA


{s_sadeg , n_bousbia}@esi.dz
Ecole nationale Supérieure d’Informatique
(ESI)
CHAPITRE IV

CLASSES INTERNES ET
ENUMÉRATIONS
1. CLASSES INTERNES
4

Classe interne
• Une classe est dite interne lorsque sa définition est située
à l’intérieur d’une autre classe.

• Pourquoi utiliser des classes internes ?


• Groupement logique de classes: Si une classe n’est utile qu’à une
seule autre classe, il est logique de la mettre à l’intérieur de cette
dernière
• Augmenter l’encapsulation: si une classe B a besoin d’accéder aux
membres privés d’une classe A, en cachant B dans A, les membres
de A ne seront accessibles que par B.
• Meilleure lisibilité et maintenabilité du code: en mettant le code de
petites classes internes à l’intérieur de leurs classes externes
5

Types de classes internes


• Les classes internes ont essentiellement pour but de
simplifier l’écriture du code de la programmation
évènementielle (dans la programmation graphique),
même si elles peuvent être utilisées en dehors de ce
contexte.

• Il y a plusieurs types de classes internes:


• Les classes internes simples (non statiques) (inner classes)
• Les classes internes statiques (static nested classes)
• Les classes locales (local classes)
• Les classes anonymes (anonymous inner classes)
6

Classe interne non statique


• Elle est définie à l’intérieur d’une autre classe (appelée
principale, englobante ou externe) en tant que membre de
cette dernière.
• Elle a l’avantage de pouvoir accéder aux autres membres de la
classes même s’il sont privés

class E //définition d’une classe usuelle dite


//externe, principale ou englobante
{...... //méthodes et données de la classe E
class I //Définition d’une classe interne à la
classe E
{…. // méthodes et données de la classe I
}
….. // autres méthodes et données de la
classe E
}
7

Utilisation d’une classe interne


• La définition d’une classe interne I est utilisable au sein de la
classe principale E.

Exemple 1
class E
{public void fe() // méthode de E
{ I i = new I(); //Création d’un objet de type I; Sa
//référence est locale à la méthode fe
}
class I
{….
}
…..
}
• Ici, une des méthodes d’un objet de type E utilise un objet de type I
8

Utilisation d’une classe interne


• On peut aussi trouver une ou plusieurs références à des objets
de type I au sein de la classe E comme dans cet exemple:

Exemple 2

class E
{
private I i1, i2; // les champs i1 et i2 sont des
//références à des objets de type I

class I
{….
}
…..
}
9

Lien entre objet interne et objet externe


• En quoi la définition d’une classe «I» interne à une classe «E»
diffère-t-elle d’une définition d’une classe I externe à la classe
E?
• Les objets correspondant à cette situation de classe interne
jouissent de trois particularités
1. Un objet de la classe I est associé au moment de sa création à un
objet de type E dont on dit qu’il lui a donné naissance. Dans
l’exemple 1, l’objet de type I sera associé à l’objet de type E
auquel sera appliquée la méthode fe.
2. Un objet d’une classe interne I a toujours accès aux champs et
méthodes (même privés) de l’objet de type E qui lui a donné
naissance (mais pas aux autres objets de E)
3. Un objet de type E a toujours accès aux champs et méthodes
(même privés) d’un objet de type I auquel il a donné naissance

Remarques:
• Une méthode statique d’une classe externe ne peut créer aucun objet
d’une classe interne.
• Une classe interne ne peut contenir de membres statiques
10

Déclaration et création d’un objet d’une classe


interne
• En théorie (mais c’est rarement exploité), java permet d’utiliser une classe interne
depuis une classe indépendante (non englobante). Mais il faut quand même
rattacher un objet d’une classe interne à un objet de sa classe englobante, en
utilisant une syntaxe particulière de new.
Exemple
class E
{......
class I
{….
}
…..
}
En dehors de E, on peut déclarer une référence à un objet de type I, mais la
création d’un objet de type I ne peut se faire qu’en le rattachant à un objet de type E
:
E e; E.I i;
E e = new E();
i = e.new I();
11

Exemple
class Cercle public void affiche ()
{ { System.out.print ("cercle de rayon "
private Centre c ; + r + " de centre ") ;
private double r ; c.affiche() ;
}
class Centre // definition public void deplace (int dx, int dy)
//interne à Cercle { c.x += dx ; c.y += dy ; // ici, on a
{ bien accès a x et y
private int x, y ; }
public Centre (int x, int y) }
{ this.x = x ;
this.y = y ; public class TestCercle
} { public static void main (String
public void affiche() args[])
{ System.out.println (x + ", " {
+ y) ; Cercle c1 = new Cercle(1, 3, 2.5);
} c1.affiche();
} //cercle de rayon 2.5 de centre 1, 3
public Cercle (int x, int y, double r) c1.deplace (4, -2) ;
{ c = new Centre (x, y) ; c1.affiche();
this.r = r ; // cercle de rayon 2.5 de centre 5, 1
} }
}
12

Masquage (shadowing)

• Si une variable membre ou le nom d’un paramètre dans une


classe interne a le même nom qu’une autre déclaration dans
sa classe externe, alors elle masque cette dernière. De ce fait,
on ne peut pas désigner cette déclaration par son nom
seulement

• Une syntaxe particulière est utilisée pour accéder explicitement


aux champs et méthodes d'instance de son objet englobant.
Cette syntaxe n'est nécessaire que pour référencer un membre
d'une classe englobante qui est masqué par un membre du
même nom dans la classe interne (ce qui est à éviter !) :
• Nom_Classe_Englobante.this.Nom_Membre
13

public class ShadowTest {


x = 23
public int x = 0; this.x = 1
class FirstLevel {
ShadowTest.this.x = 0

public int x = 1;

void methodInFirstLevel(int x) {
System.out.println("x = " + x);
System.out.println("this.x = " + this.x);
System.out.println("ShadowTest.this.x = " + ShadowTest.this.x);
}
}

public static void main(String... args) {


ShadowTest st = new ShadowTest();
ShadowTest.FirstLevel fl = st.new FirstLevel();
fl.methodInFirstLevel(23);
}
}
14

Classes internes statiques


• Les objets des classes internes vues jusqu’à maintenant
étaient toujours associés à un objet d’une classe
englobante. On peut créer une classe interne « autonome »
en utilisant le mot clé static:

class E // classe englobante


{...... //méthodes et données de la
//classe E
public static class I //Définition dans la classe E
//d’une classe interne autonome
{….
}
…..
}
15

Classes internes statiques


• A l’extérieur de la classe E, on peut instancier un objet de
la classe I de cette façon:

E.I i = new E.I();

• L’objet i n’est associé à aucun objet de type E. La classe I


n’as accès à aucun membre de E, sauf s’il s’agit de
membres statiques.
16

Classes locales
• On peut définir une classe interne I dans une méthode f d’une
classe E. Dans ce cas l’instanciation d’objets de type I ne peut
se faire que dans f. En plus des accès déjà décrits, un objet de
type I a alors accès aux variables finales de f.

public class E{………


void f(){
I i = new I();
final int n = 15;
float x;

class I{ // c’est une classe interne à la classe E


…… // et locale à la méthode f. ici on a accès
// à n mais pas à x
}

}
……
}
17

Classes anonymes
• Les classes internes anonymes (anonymous inner-
classes) sont des classes internes qui ne possèdent pas
de nom. Elles ne peuvent donc être instanciées qu'à
l'endroit ou elles sont définies.
• Ce type de classes est très pratique dans la gestion des
événements ou lorsqu'une classe doit être utilisée une
seule fois
• La syntaxe de définition d’une classe anonyme ne
s’applique que dans deux cas:
• Classe anonyme dérivée d’une autre
• Classe anonyme implémentant une interface
18

Classes anonymes
Classe anonyme dérivée d’une autre classe
class A {
public void afficher() {
System.out.println("je suis un A ");
}
}

public class ExempleAnonyme1 {


public static void main(String args[]) {
A a;
a = new A() { //début de la classe anonyme
public void afficher() {
System.out.println(" je suis une classe anonyme dérivée de A");
}
}; // fin: le point-virgule est obligatoire

a.afficher(); //appel la méthode afficher de la classe anonyme


}
}
19

Classes anonymes
Classe anonyme implémentant une interface

interface Affichable {
public void afficher();
}

public class exempleAnonyme2 {


public static void main(String args[]) {
Affichable a;
a = new Affichable() {//début de la classe anonyme
public void afficher() {
System.out.println("je suis une classe anonyme implémentant
l’interface Affichable ");
}
}; // le point-virgule est obligatoire

a.afficher(); // Appel afficher de la classe anonyme


}
}
20

Classes internes et droits d’accès


Les classes internes sont concernées par les droits d’accès
mais leur signification est différente et se rapproche de la
définition des droits d’accès aux membres:
• Une classe interne déclarée publique est accessible
partout où sa classe externe l’est.
• Une classe interne déclarée privée (ce qui n’est pas
utilisable pour une classe externe) n’est accessible que
depuis sa classe externe
• Sans aucun mot clé, la classe interne n’est accessible
que depuis les classes du même paquetage.
1. ENUMÉRATIONS
22

Enumérations: définition
• Une énumération (un type énuméré) est un type de
données spécial qui permet à une variable de prendre ses
valeurs dans ensemble fini.
• La variable doit être égale à l’une des valeurs prédéfinies
pour elle.

• Les énumérations sont utilisées lorsque l’on veut


représenter un ensemble fixe de valeurs.

• Exemple: la variable PointCardinal qui peut prendre les


valeurs (NORD, SUD, EST, OUEST)
23

Enumérations: déclaration
• En java, une énumération est déclarée comme une classe
mais en utilisant le mot clé enum au lieu de class.

• Exemple:

public enum Saison { HIVER, PRINTEMPS, ETE, AUTOMNE}

• Remarque: les champs d’un type énuméré sont écrits en


lettres majuscules car ce sont des constantes mais ce n’est
pas obligatoire
24

Enumération: une classe particulière


• En Java, une énumération est une particulière
• Elle étend la classe Enum, qui elle-même étend la
classe Object, comme toutes les classes en Java.
• Les valeurs d'une énumération sont les seules instances
possibles de cette classe. Ce sont des instances finales
(non modifiables).
• Dans l’exemple précédent, Saison comporte quatres
instances constantes: Saison.HIVER,
Saison.PRINTEMPS, Saison.ETE et Saison.AUTOMNE.
• Une énumération peut avoir des constructeurs, des
méthodes, des champs, ….etc.
25

Méthodes d’une énumération (1)


• Tous les types énumérés héritent de java.lang.Enum. Il
héritent donc de ses méthodes:
• int ordinal(): elle renvoie leur position dans l'ordre de déclaration (à partir
de zéro)
• String name() qui renvoie leur nom

Exemple:
Saison season= Saison.PRINTEMPS;
System.out.println("la Saison " + season.name() + " est à la position: " +
season.ordinal() ) ;
//affiche
la Saison PRINTEMPS est à la position: 1
26

Méthodes d’une énumération (2)


• Tous les types énumérés héritent aussi de méthodes de
Object redéfinies dans java.lang.Enum
• 1) equals: elle permet de tester l’égalité de deux valeurs
(instances) d’une énumération. On peut aussi utiliser l’opérateur
== qui compare les adresses (car les instances sont constantes)

System.out.println(Saison.PRINTEMPS.equals(Saison.HIVER)) ;
System.out.println(Saison.PRINTEMPS.equals(Saison.PRINTEMPS)) ;
System.out.println(Saison.PRINTEMPS==Saison.HIVER) ;
System.out.println(Saison.PRINTEMPS==Saison.PRINTEMPS) ;
//affiche
false
True
false
True
27

Méthodes d’une énumération (3)


• 2) compareTo: elle sert à ordonner les valeurs d’une
énumération en utilisant la qui se base sur l’ordre de déclaration
des valeurs

System.out.println(Saison.PRINTEMPS.compareTo(Saison.HIVER)) ;
System.out.println(Saison.PRINTEMPS.compareTo(Saison.PRINTEMPS)) ;
System.out.println(Saison.PRINTEMPS.compareTo(Saison.ETE)) ;

//affiche
1
0
-1
28

Méthodes d’une énumération (4)


Tous les types énumérés possèdent aussi deux méthodes
statiques générées par le compilateur
1)TypeEnuméré[] values(): renvoie une copie d'un tableau contenant
toutes les valeurs de l'énumération dans l'ordre de déclaration

Saison seasons[]= Saison.values();


System.out.println(Arrays.toString(seasons));
//affiche
[HIVER, PRINTEMPS, ETE, AUTOMNE]
29

Méthodes d’une énumération (5)


Tous les types énumérés possèdent aussi deux méthodes
statiques générées par le compilateur
• 2)TypeEnuméré valueOf(String name): retourne la valeur
énumérée à partir de sa chaîne de caractères.
Saison season = Saison.valueOf(« HIVER") ;
// season prend la valeur Saison.HIVER

Une deuxième version de cette méthode existe dans la


classe Enum, et prend le nom de l'énumération en paramètre
valueOf(Class<T> enumType, String name)

Saison season = Enum.valueOf(Saison.class, « HIVER") ;


// season prend la valeur Saison.HIVER
30

Utiliser une énumérations dans un « if »


• On peut comparer une référence vers un objet de type
énumération avec une des valeurs possibles.

• Exemple
public enum Couleur {VERT, BLEU, ROUGE}
……
Couleur color ;
……
if( color == Couleur.VERT) { }
else if( color == Couleur.BLEU) { }
else if( color == Couleur.ROUGE) { }
31

Utiliser une énumération dans un « switch »


• Si une énumération contient beaucoup de constantes, il est
plus judicieux d’utiliser un switch

• Exemple
public enum Niveau { UN_CPI, DEUX_CPI,UN_CS, DEUX_CS,
TROIS_CS}
……
Niveau niv ;
……
switch (niv) {
case UN_CPI: ........... ; break;
case DEUX_CPI : ........... ; break;
case UN_CS : …………. ; break;
case DEUX_CS : ........... ; break;
case TROIS_CS : …….... ; break;
}
32

Parcourir une énumération


• Pour parcourir les valeurs d’une énumération on utilise
une boucle foreach et un tableau contenant les valeurs de
cette énumération retourné par la méthode values()
• Example:
for (Saison s : Saison.values() )
System.out.println(s.toString()) ;

//affiche
HIVER
PRINTEMPS
ETE
AUTOMNE
33

Ajouter des champs et des méthodes à une


énumération (1)
1) Méthodes: Il est possible de définir des méthodes à l’intérieur
d’une énumération. Notez la syntaxe particulière

enum Saison { HIVER, PRINTEMPS, ETE, AUTOMNE;


//affiche
public void afficher () { HIVER
System.out.println (toString() ) ;} PRINTEMPS
} ÉTÉ
AUTOMNE
public class CoursEnum {
public static void main(String[] args) {
for (Saison s : Saison.values() )
s.afficher() ;
}
}
34

Ajouter des champs et des méthodes à une


énumération (2)
• 2) Constructeurs: Il est possible de doter une énumération d’un ou
plusieurs constructeurs. Il est appelé au moment de l’instanciation des
objets constants du type énuméré.

• Il sert à associer une propriété qui prend une valeur particulière pour
chacune de ces instances.

• S’il nécessite des arguments, ces derniers doivent être mentionnés à la


suite du nom de la constante.

• Les constructeurs des enum sont implicitement privés (même si


l'accesseur private n'est pas spécifié). Ils n'acceptent donc pas de
modificateurs d’accès public ou protected.
35

Ajouter des champs et des méthodes à une


énumération (3)
exemple
Saison { HIVER("pluvieux"), PRINTEMPS("ensoleillé"), ETE("chaud"), AUTOMNE("variable");
private String temps ;
private Saison(String temps) {
this.temps = temps ;
}
public String getTemps() {
return this.temps ;
}
}
public class CoursEnum { // affiche
public static void main(String[] args) {
for (Saison s : Saison.values() ) pluvieux
System.out.println (s.getTemps()); ensoleillé
} chaud
} variable
36

Enumérations et héritage
• Seules les enum héritent de java.lang.Enum.
• Une classe ne peut hériter de Enum
• Une classe ne peut hériter d'une enumération
• Une énumération ne peut hériter d'une classe

• public class A extends Enum { } // erreur


• public class A extends Saison { } // erreur
• public enum Saison extends A { } // erreur
• public enum Meteo extends Saison { } // erreur

Vous aimerez peut-être aussi