Vous êtes sur la page 1sur 41

Programmation Orientée Objet (POO)

Concept de classe
Une classe est le support de l'encapsulation : c'est un ensemble de
données et de fonctions regroupées dans une même entité. Une classe est
une description abstraite d'un objet. Les fonctions qui opèrent sur les
données sont appelées des méthodes. Instancier une classe consiste à
créer un objet sur son modèle. Entre classe et objet il y a, en quelque
sorte, le même rapport qu'entre type et variable.

Java est un langage orienté objet : tout appartient à une classe sauf les
variables de type primitif.
Concept de classe
Pour accéder à une classe il faut en déclarer une instance de classe ou
objet.

Une classe comporte sa déclaration, des variables et la définition de ses


méthodes.

Une classe se décompose en deux parties : un en-tête et un corps. Le


corps peut être divisé en 2 sections : la déclaration des données et des
constantes et la définition des méthodes. Les méthodes et les données
sont pourvues d'attributs de visibilité qui gère leur accessibilité par les
composants hors de la classe.
Concept d’objet
Un objet sera défini comme étant une entité concrète ou abstraite du
monde réel. Les objets contiennent des attributs et des méthodes.
Chaque objet sera caractérisé par un jeu de données (attributs ou
champs).

Les attributs sont des variables ou des objets nécessaires au


fonctionnement de l'objet.

La classe est la description d'un objet. Un objet est une instance d'une
classe. Pour chaque instance d'une classe, le code est le même, seules les
données sont différentes à chaque objet.
Définition d’une classe
Exemple:

public class Point { //Entête de la classe


private double x ; //champ x d’un objet point
private double y ; //champ y d’un objet point

//Méthode pour initialiser un objet de type point


public void initialize ( double abs, double ord){
x = abs ;
y = ord ;
}
}
Définition d’une classe
Les champs x et y (déclarés private) ne sont visibles qu’à l’intérieur de la
classe : c’est le principe de l’encapsulation des données. Les données ne seront
accessibles que par l’intermédiaire de méthodes prévues à cet effet.

La méthode initialize ne fournit aucun résultat, c’est une méthode de


type void. Elle est accessible depuis n’importe quel programme (grâce au mot
clé public) et permet d’attribuer des valeurs initiales aux champs de l’objet.

Remarques:
Une méthode peut être déclarée private. Dans ce cas, elle n’est visible qu’à
l’intérieur de la classe où elle est définie.
Il est fortement déconseillé de déclarer des champs avec le mot clé public, cela
nuit à l’encapsulation des données.
Création d’objet
La création d’un objet (on parle d’instanciation) se fait avec le mot clé
new.

Exemple:
int a ; //réservation de mémoire pour contenir une
//variable entière

Point p ; //cette déclaration ne réserve pas de mémoire


//pour l’objet p mais simplement une
//référence à un objet de type Point

p = new Point() ; //Un objet Point est créé et sa


//référence est mise dans la variable p
Manipulation d’objets
Une fois la classe instanciée, on peut appliquer n’importe quelle
méthode ( non statique et définie dans le classe) à l’objet créé.

Exemple:

p.initialize (3,8) ; //On applique ici la méthode


//initialize à l’objet p avec
//comme paramètres x = 3 et y = 8

L’opérateur "." est appelé opérateur d’accès. Il permet d’accéder aux


champs de l’objet mais aussi d’appliquer des méthodes aux objets.
Exemple
public class Point { //Entête de la classe
private double x ,y; //champ x et y d’un objet point

//Méthode pour initialiser un objet de type point


public void initialize ( double abs, double ord){
x = abs ;
y = ord ;
}

public static void main (String A[]) {

Point t = new Point();


t.initialize(23, 3);
System.out.println(t);
System.out.println("x = "+t.x+" et y = " +t.y);
}
}
Le constructeur
En Java, la création d’objets se fait par allocation dynamique grâce à
l’opérateur new qui appelle une méthode particulière: le constructeur.

Dans l’exemple précédent, il n’y avait pas de constructeur. C’était plutôt


la méthode initialize qui se chargeait d’initialiser correctement les
champs d’un objet de type Point.

Un constructeur permet d’automatiser l’initialisation d’un objet.

Un constructeur est une méthode qui porte le même nom que la classe
et qui est sans valeur de retour. Il peut disposer d’un nombre quelconque
d’arguments.
Le constructeur
public class Point1 {
private double x ,y; //champ x et y d’un objet point
//Constructeur pour initialiser un objet de type point
public Point1 ( double abs, double ord){
x = abs ;
y = ord ;
}
//Fonction permettant de déplcaer la position d'un point du plan
public void deplace (double dx, double dy){
x += dx ;
y += dy ;
}
public static void main(String A[]){
Point1 t = new Point1(3, 9);
t.deplace(5, 5);
System.out.println("x = "+t.x+" et y = "+t.y);
}
}
Quelques règles sur les constructeurs
Une classe peut comporter plusieurs constructeurs, ils se différencient par le
nombre et le type de leurs arguments.

Une classe peut ne pas disposer de constructeur, dans ce cas les objets serons
instancier avec le constructeur par défaut (constructeur sans arguments). Mais
dès qu’une classe possède un constructeur, le constructeur par défaut ne peut
plus être utilisé.

Une classe peut disposer d’un constructeur sans arguments (appelé souvent
pseudo-constructeur) qui est bien différent du constructeur par défaut.

Un constructeur peut appeler un autre constructeur de la même classe.

Un constructeur peut être déclaré public ou privé.


Déclaration de constante: final
Exemple:
public class Constante{
private final int NOMBRE, MAX = 42 ;

public Constante (int nbre){


NOMBRE = nbre ;
}

public double diviser(){


return NOMBRE / MAX ;
}
}

La valeur assignée à un champ final ne pourra pas être changée dans le


programme.
Affectation et comparaison d’objet
Exemple:

Point a = new Point (2, 5) ;


Point b = new Point (9.3, 0) ;

a = b ; // a et b désignent désormais le même


//objet: a = (9.3, 0)

L’ancienne référence ainsi que l’ancienne valeur de a seront


candidates au ramasse-miette (garbage collector)
Référence nulle: le mot clé null
Les variables locales de type objet doivent toujours être initialisées.

Exemple:
public class Point1 {
private double x ,y;
public Point1 ( double abs, double ord){
x = abs ;
y = ord ;
}
public Point1 ajouter (Point1 p){
Point1 r = null ;
r.x = this.x + p.x ;
r.y = this.y + p.y ;

return r ;
}
}
Comparaison d’objets
Exemple:
public class Point1 {
private double x ,y;
public Point1 ( double abs, double ord){
x = abs ;
y = ord ;
}
public static void main(String A[]){
Point1 t1 = new Point1(3, 9);
Point1 t2 = new Point1(3, 9);
System.out.println(t1 == t2); //false
System.out.println(t1.equals(t2)); //false
}

== teste s’il s’agit du même objet.


equals teste l’égalité de contenu (les références )
Variables de classes: le mot clé static
Elles ne sont définies qu'une seule fois quel que soit le nombre
d'objets instanciés de la classe. Leur déclaration est accompagnée du
mot clé static.

Exemple:
public class MaClasse {
static int compteur = 0;
}
Variables de classes: le mot clé static
L'appartenance des variables de classe à une classe entière et non à un objet
spécifique permet de remplacer le nom de la variable par le nom de la
classe.

Exemple:

int c = MaClasse.compteur; //permet d’accéder au champ


//compteur de la classe MaClasse

Ce type de variable est utile pour compter par exemple le nombre


d'instanciations de la classe qui est faite.
Méthodes de classe
Une méthode de classe, ayant un rôle indépendant de toute instance de la
classe, doit être déclarée avec le mot clé static et elle ne pourra être
appliquée à aucun objet de cette classe, contrairement aux méthodes
d’instances.

L’appel de la méthode ne nécessitera que le nom de la classe.

Une méthode statique ne peut pas agir sur des champs usuels, c’est-à-
dire non statiques.
Méthodes de classe
Exemple:

public class MethodeStatique{


private static long nombreInstances ;
private long n ;

public MethodeStatique (long k) {


nombreInstances ++ ;
n = k ;
}

public void affiche(){


System.out.println ("nombre d’objets créés :" +
nombreObjet( ) );
}

public static long nombreObjet(){


retun nombreInstances ;
}
}
Surdéfinition de méthodes
La surdéfinition (appelée encore surcharge ou overloading) d'une méthode
permet de définir plusieurs fois une même méthode avec des arguments
différents. Le compilateur choisit la méthode qui doit être appelée en
fonction du nombre et du type des arguments.

Il est donc possible de donner le même nom à deux méthodes différentes à


condition que les signatures de ces deux méthodes soient distinctes. La
signature d'une méthode comprend le nom de la classe, le nom de la
méthode et les types des paramètres.
Surdéfinition de méthodes
Exemple:
public class Compte {
private int numero ;
private double solde ;

public Compte (int num, double sol){


numero = num ;
solde = sol ;
}

public void debiter (double montant){


solde -= montant ;
}

public void debiter (double montant, double taxe){


solde -= montant * (1 + taxe) ;
}
}
Surdéfinition des constructeurs
Les constructeurs peuvent être surdéfinis comme toute autre méthode.
Exemple:
public class Compte {
private int numero ;
private double solde ;
private String prop ;

public Compte (int num, double sol){


numero = num ;
solde = sol ;
}

public Compte (int num, double sol, String nom){


numero = num ;
solde = sol ;
prop = nom ;
}
}
Les méthodes: Transmission de paramètres
Lorsqu’un objet est passé en paramètre, ce n’est pas l’objet lui-même
qui est passé mais une référence sur l’objet. La référence est
transmise par valeur et ne peut pas être modifiée mais l’objet peut
être modifié via un appel de méthode.

En Java, la transmission de paramètre se fait toujours par valeur.


Transmission de paramètres
Exemple 1:
public class TransParam{
private int t ;

public TransParam (int r){


t = r ;
}

public double puissance (double s){ // s est un argument muet


return Math.pow(s, t)
}

public static void main (String [] args){


TransParam tp = new TransParam (23) ;
System.out.println(tp.puissance(3.2)) ; // 3.2 est un
//argument effectif
}
}
Transmission de paramètres
public class Point {
private double x ,y;
public Point ( double abs, double ord){
x = abs ;
y = ord ;
}
public boolean coincide (Point p){
return (p.x == x && p.y == y) ;
}

public static void main (String args[]){


Point p1 = new Point (2, 7) ;
Point p2 = new Point (2, 7.1) ;
System.out.println (p1.coincide(p2)) ;
//ici, c’est la référence de l’objet p2 qui est donnée
//en argument, donc impossible de la modifier
}
}
Autoréférence : la variable this
La variable this sert à référencer dans une méthode l'instance de l'objet
en cours d'utilisation. this est un objet qui est égale à l'instance de l'objet
dans lequel il est utilisé.

Exemple: La méthode coincide de l’exemple précédent peut être


remplacée par

public boolean coincide (Point p){


return (p.x == this.x && p.y == this.y) ;
}
Dans l’appel a.coincide(b), le this désigne l’objet courant, c’est-à-
dire a
Autoréférence : la variable this
L’utilisation de this est très pratique dans l’écriture des méthode et surtout des
constructeurs.
Exemple:
public Personne (String lname, String fname ){
nom = lname ;
prenom = fname ;
}
pourra être remplacé par
public Personne (String nom, String prenom ){
this.nom = nom ;
this.prenom = prenom ;
}

Remarquez que les noms des arguments du constructeurs et des attributs sont
identiques.
Appel d’un constructeur dans un autre
Un constructeur peut appeler un autre constructeur de la même classe avec le mot clé
this. L’objectif majeur de l’utilisation de this est de simplifier le code.
Exemple: la classe
public class Compte {
private int numero ;
private double solde ;
private String prop ;

public Compte (int numero, double solde){


this.numero = numero ;
this.solde = solde ;
}

public Compte (int numero, double solde, String prop){


this.numero = numero ;
this.solde = solde ;
this.prop = prop ;
}
}
Appel d’un constructeur dans un autre
Peut être réécrite comme suit
public class Compte {
private int numero ;
private double solde ;
private String prop ;

public Compte (int numero, double solde){


this.numero = numero ;
this.solde = solde ;
}

public Compte (int numero, double solde, String prop){


this (numero, solde)
this.prop = prop ;
}
}
L’appel de this doit obligatoirement être la première instruction du constructeur
appelant.
Les classes internes
Une classe interne est une classe définie à l’intérieur d’une autre
classe.

Les classes internes (inner class ) peuvent se situer à différents


niveaux de la classes principale. On en distingue 4:
Les classes internes simples
Les classes internes statiques
Les classes locales
Les classes internes anonymes

Une classe interne est souvent utilisée pour définir une classe à l’endroit où
une seule autre classe en a besoin, pour définir des classes de type adapter.
Les classes internes simples
public class ClasseParente {
private int x = 10 , y = 20;
public int addition () { return (x + y); }
public class ClasseInterne {//DEBUT CLASSE INTERNE
static int p = 20; //erreur de compilation,
static final int k = 12; //constante statique
public int multiplier(){
return x*y + addition( ); }
} //FIN CLASSE INTERNE
public static void main(String [] args) {
ClasseParente ob_out = new ClasseParente();
//ClasseInterne ob_in0 = new ClasseInterne(); IMPOSSIBLE
ClasseInterne ob_in = ob_out.new ClasseInterne();
System.out.println (ob_in.multiplier());
// System.out.println (ob_out.multiplier());//ERREUR
// System.out.println (ob_in.addition ( )); IMPOSSIBLE
} }
Les classes internes simples
Remarques:
Une classe interne peut être déclarée avec n’importe quel modificateur
d’accès (public, private, protected, par défaut) et les modificateurs
abstract, final, static.

Les classes internes ne doivent pas déclarer de membres statiques, sauf


s’ils comportent le modificateur final, dans le cas contraire, une erreur
de compilation se produit. Toutefois, les membres statiques de la classe
externe peuvent être hérités sans problèmes par la classe interne.

Les classes imbriquées sont capables d’accéder à toutes les variables et


méthodes de la classe parente, y compris celles déclarées avec un
modificateur private.
Les classes internes simples
La notation particulière
ClasseInterne ob_in = ob_out.new ClasseInterne() ;

spécifie que l’objet créé est une instance de la classe interne associée à
l’objet résultant de l’instanciation d’une classe de haut niveau.

L’instanciation de la classe interne passe obligatoirement par une


instance préalable de la classe d’inclusion.

La classe parente est d’abord instanciée, puis c’est au tour de la classe


interne de l’être par l’intermédiaire de l’objet résultant de la
première instance.
Les classes internes simples
Il est possible d’utiliser une méthode de la classe parente pour créer directement
une instance de la classe interne. Toutefois, lors de l’appel de la méthode, il sera
nécessaire de créer une instance de la classe d’inclusion.

Exemple:

public class ClasseParente02 {


private int x = 10, y = 20;
public int addition ( ){
ClasseInterne02 obj_in = new ClasseInterne02( );
return (x + y)+ obj_in .multiplier ( );
}
public class ClasseInterne02{
public int multiplier ( ){ return x*y ; }
}
}
Les classes internes simples
public class ClasseParente03 {
private int x = 10, y = 20 ;
public int addition( ){
ClasseInterne03 obj_in= new ClasseInterne03(10,10);
return (x + y)+ obj_in.multiplier();
}
public class ClasseInterne03{
private int x = 12; private int y = 14;
public ClasseInterne03 (int x, int y){
this.x = x + ClasseParente03.this.x;
this.y = y + ClasseParente03.this.y;
}
public int multiplier( ){
return x*y ;
}
} }
Les classes internes statiques
Contrairement à une classe interne simple, une classe statique interne ne
peut accéder qu’aux variables statiques de la classe parente.

Les classes internes statiques peuvent accéder à l’ensemble des membres


statiques de leur classe parente, à l’instar des méthodes de classe.
Les classes internes statiques
public class Parent04 {
private static int x = 1, y = 2; private int z = 3;
public int addition ( ){ return x + y + z;}
public static int multiplier( ){ return x*y;}
public static class Interne04{
private static int k = 1;
private int p = 2;
public void diviser(){
System.out.println(new Parent04().addition()/p+x+y);
}
public static void imprimer(){
System.out.println ( multiplier ( ) / x+y+k );}
}
public static void main(String [ ] args) {
Parent04.Interne04.imprimer ();
new Parent04. Interne04().diviser ( );} }
Les classes locales
Une classe locale est définie à l'intérieur d'une méthode ou un bloc, et
agît librement et essentiellement au sein de cette dernière. Elle peut
être static ou non.
Il n'est possible de déclarer des classes locales, dont la portée est limitée
au bloc, qu'avec les modificateurs final ou abstract. Les modificateurs
suivants: public, protected, private et static, sont interdits.
Les données membres d'une classe externe peuvent être accédés par la
classe locale.
Seules les variables locales et les paramètres de la méthode d'inclusion,
déclarées avec le modificateur final, peuvent être exploitées par les
classes internes locales, sinon une erreur se produit lors de la
compilation. De plus, ces variables doivent être impérativement
initialisées avant leur emploi dans la classe locale.
Les classes locales
public class ClasseExterne {
private int x,y;
private static int z;
public void addition( int p){
final int k = 9;
int u = 121;// inutilisable dans ClasseLocale
class ClasseLocale {
boolean verif(){
if (x+ y+ k = = z) return true;
else return false;
}
}
}// fin bloc de méthode
}

p et u ne peuvent pas être utilisés dans ClassLocale. Par contre , k est déclarée
finale donc on peut l’utiliser.
Les classes anonymes
Les classes anonymes (anonymous classes) sont déclarées immédiatement
après l'expression d'instanciation d'une classe, permettant directement
d'étendre ou d'implémenter respectivement la classe ou l'interface
instanciée.
Elles sont définies et instanciées à la volée sans posséder de nom.
new Classe([Liste d'arguments]) {... };
new Interface ( ) {... };
Les classes anonymes obéissent aux mêmes restrictions que les classes
locales et de plus, ne peuvent ni être abstraites (abstract) ni être statiques
(static).
Par contre, elles portent toujours implicitement le modificateur final.
En fait, aucun modificateur n'est permis dans une déclaration de classe
anonyme.
On verra l’utilité des classes anonymes en programmation évènementielle.