L'auto-référencement
La surcharge des fonctions et procédures
1. L'AUTO-REFERENCEMENT
1.1. Principe
Chaque méthode peut travailler sur les données de l'objet ayant servi à son appel en indiquant uniquement le nom des données.
Elle peut également appliquer une méthode de la classe à l'objet ayant servi à son appel, en indiquent uniquement le nom de la méthode.
La méthode peut retourner l'une des données.
Mais il est possible que la méthode ait besoin de retourner l'intégralité de l'objet ayant servi à son appel. Par exemple, on peut avoir besoin d'une méthode Compar_moyenne qui compare la moyenne de deux élèves (l'instance paramètre implicite et une instance paramètre explicite) et retourne l'instance de l'élève ayant la moyenne la plus élevée. On supposera qu'il n'y a pas d'ex-aequos.
Déclaration de la classe élève
CLASSE élève
privé
el_nom : chaîne de caractères
el_oral, el_écrit : réel
FONCTION moyenne () : réel
public
PROCEDURE initial (données : nom : chaîne de caractères, or, ec : réels)
PROCEDURE affich () /* Affiche le nom et la moyenne de l'élève */
FONCTION compar_moyenne (donnée : e : élève) : élève
FCLASSE
Définition de la fonction compar_moyenne
FONCTION élève::compar_moyenne (donnée : e: élève) : élève
DEBUT
SI moyenne () > e.moyenne ()
ALORS
RETOURNER moi-même /* On retourne la valeur de l'objet ayant servi à l'appel */
SINON
RETOURNER e
FSI
FIN
Exemple d'utilisation de compar_moyenne
Soit un tableau tabélève de 5 éléments de classe élève préalablement initialisé (par des appels à la méthode initial), une variable meilleur de classe élève et une variable entière i. On souhaite déterminer quel élève a la moyenne la plus élevée puis afficher le nom et la moyenne de cet élève :
meilleur ßtabélève[1];
POUR i à 2 A 5
meilleur ß tabélève[i].compar_moyenne (meilleur)
FPOUR
AFFICHER "Meilleur élève : "
meilleur.affich ();
1.2. Codage en Java
Java permet au programmeur de désigner l’objet ayant servi à l'appel de la méthode par this.
Pour retourner la valeur du paramètre implicite, il faut donc retourner this.
Définition de la fonction compar_moyenne
public eleve compar_moyenne (eleve e)
{
if (moyenne() > e.moyenne())
return this
else
return e;
}
Exemple d'utilisation de compar_moyenne
meilleur = tabeleve[0];
for (i=1; i<5; i++)
{
meilleur = tabeleve[i].compar_moyenne (meilleur);
}
System.out.println ("Meilleur élève : ");
meilleur.affich();
2. LA SURCHARGE DE FONCTIONS ET PROCEDURES
2.1. Définitions
Une fonction ou procédure est repérée par sa signature constituée de son nom et du type de chacun de ses paramètres. Le type du retour pour une fonction n'est pas pris en compte dans la signature.
Surcharger une fonction ou une procédure signifie définir plusieurs fonctions ou procédures ayant le même nom mais des signatures différentes.
Cette surcharge est possible pour des fonctions ou procédures extérieures à une classe et également pour des méthodes d'une classe.
2.2. Surcharge de fonctions ou de procédures extérieures à une classe
2.2.1. Ecriture de fonctions ou procédures surchargées
On souhaite par exemple pouvoir appeler une fonction nommée extractch qui permette d'extraire une suite de caractères d'une chaîne de différentes façons possibles :
§ en transmettant la chaîne source, la position de l'élément à partir duquel il faut effectuer l'extraction et le nombre de caractères à extraire,
§ en transmettant la chaîne source, le 1er caractère à partir duquel il faut effectuer l'extraction et le nombre de caractères à extraire,
§ en transmettant la chaîne source et la position de l'élément à partir duquel il faut effectuer l'extraction, dans ce cas il y a extraction d'un caractère.
La position transmise est supposée valide (donc comprise entre 1 et la longueur de la chaîne).
FONCTION extractch (données : ch : chaîne de caractères, pos, lg : entier) : chaîne de caractères
DEBUT
RETOURNER SSCHAINE (ch, pos, lg)
FIN
FONCTION extractch (données : ch:chaîne de caractères, c:caractère, lg:entier) : chaîne de caractères
VAR pos : entier
DEBUT
pos ß RANG (ch, c, 1)
SI pos <> 0
ALORS
RETOURNER SSCHAINE (ch, pos, lg)
SINON
RETOURNER ""
FSI
FIN
FONCTION extractch (données : ch : chaîne de caractères, pos : entier) : chaîne de caractères
DEBUT
RETOURNER SSCHAINE (ch, pos, 1)
FIN
2.2.2. Utilisation
Lors de l'appel à une fonction ou procédure surchargée, il y a recherche de correspondance entre le type des paramètres effectifs et celui des paramètres formels.
La correspondance doit être unique c'est-à-dire qu'un appel doit correspondre à une et une seule fonction ou procédure.
Instruction |
Fonction appelée (1, 2 ou 3) |
Résultat |
AFFICHER extractch ("BONJOUR", 2, 3) |
1 |
NJO |
AFFICHER extractch ("BONJOUR", 2) |
3 |
N |
AFFICHER extractch ("BONJOUR", 'N', 3) |
2 |
NJO |
AFFICHER extractch ("BONJOUR", 'F', 3) |
2 |
Chaîne vide |
2.3. Surcharge de méthodes dans une classe
Le principe est identique à ce qui a été vu au §2.2.
Exemple :
Définition d'une classe date avec une fonction compar surchargée.
CLASSE date
privé
jj, mm, aaaa : entier
public
PROCEDURE initial (données : j, m, a : entier)
FONCTION compar (donnée : d2 : date) : entier /* retourne 1 si le param.
implicite > param. explicite, 0 si égalité et –1 sinon. */
FONCTION compar () : entier /* retourne 1 si le param.
implicite > date système, 0 si égalité et –1 sinon. */
FCLASSE
PROCEDURE date::initial (données : j, m, a : entier)
DEBUT
jj ßj
mm ßm
aaaa ßa
FIN
FONCTION date::compar (donnée : d2 : date) : entier
VAR tot1, tot2 : entier
DEBUT
tot1 ß aaaa * 10 ^ 4 + mm * 100 + jj
tot2 ß d2.aaaa * 10 ^ 4 + d2.mm * 100 + d2.jj
SI tot1 > tot2
ALORS
RETOURNER 1
SINON
SI tot1 = tot2
ALORS RETOURNER 0
SINON RETOURNER -1
FSI
FSI
FIN
FONCTION date::compar () : entier
VAR d2 : date
DEBUT
d2.initial (jour_système, mois_système, année_système)
tot1 ß aaaa * 10 ^ 4 + mm * 100 + jj
tot2 ß d2.aaaa * 10 ^ 4 + d2.mm * 100 + d2.jj
SI tot1 > tot2
ALORS
RETOURNER 1
SINON
SI tot1 = tot2
ALORS RETOURNER 0
SINON RETOURNER -1
FSI
FSI
FIN
Utilisation de la classe date
VAR d1 : date
/* Saisie d'une 1ère date */
AFFICHER "Saisir le jour, le mois puis l'année"
SAISIR joursaisi, moissaisi, ansaisi
d1.initial (joursaisi, moissaisi, ansaisi)
SI d1.compar () = 1
ALORS
AFFICHER "La date saisie est supérieure à la date système"
SINON
SI d1.compar () = 0
ALORS AFFICHER "La date saisie est la date du jour"
SINON AFFICHER "La date saisie est inférieure à la date système"
FSI
FSI
/* Déclaration et saisie d'une 2ème date puis comparaison avec la 1ère date */
VAR d2 : date
AFFICHER "Saisir le jour, le mois puis l'année"
SAISIR joursaisi, moissaisi, ansaisi
d2.initial (joursaisi, moissaisi, ansaisi)
SI d1.compar (d2) = 1
ALORS
AFFICHER "La 1ère date saisie est supérieure à la 2ème date saisie"
SINON
SI d1.compar (d2) = 0
ALORS AFFICHER "Les 2 dates saisies sont égales"
SINON AFFICHER "La 1 ère date saisie est inférieure à la 2ème date saisie"
FSI
FSI
2.4. Codage en Java
2.4.1. L'exemple de la classe date
La classe est nommée MaClasseDate.
Code de la classe MaClasseDate :
import java.util.GregorianCalendar;
class MaClasseDate
{
private int jj, mm, aaaa;
public void initial (int j, int m, int a)
{
jj=j;
mm=m;
aaaa=a;
}
public int compar (MaClasseDate d2 )
{
/* retourne 1 si le param. implicite > param. explicite,
0 si égalité et -1 sinon. */
int tot1 = (int)(aaaa * Math.pow(10, 4) + mm * 100 + jj);
int tot2 = (int)(d2.aaaa * Math.pow(10,4) + d2.mm * 100 + d2.jj);
if (tot1 > tot2)
return 1 ;
else
{
If (tot1 = = tot2)
return 0
else
return -1;
}
}
public int compar ()
{
/* retourne 1 si le param. implicite > date système,
0 si égalité et -1 sinon. */
MaClasseDate d2=new MaClasseDate();
// on récupère la date système
GregorianCalendar calendar = new GregorianCalendar();
int jour_système = calendar.get(GregorianCalendar.DAY_OF_MONTH);
int mois_système= calendar.get(GregorianCalendar.MONTH)+1;
int année_système=calendar.get(GregorianCalendar.YEAR);
d2.initial (jour_système, mois_système, année_système);
// pow rend un double donc il faut caster explicitement le résultat en entier
int tot1 = (int)(aaaa * Math.pow(10, 4) + mm * 100 + jj);
int tot2 = (int)(d2.aaaa * Math.pow(10,4) + d2.mm * 100 + d2.jj);
if (tot1 > tot2)
return 1 ;
else
{
If (tot1 = = tot2)
return 0
else
return -1;
}
}
}
Code de la classe Prog1date qui utilise MaClasseDate :
import java.io.*;
class Prog1date
{
public static void main (String args[]) throws IOException
{
MaClasseDate d1=new MaClasseDate();
// Saisie d'une 1ère date et comparaison avec la date système */
int joursaisi = Entrée.entier("Saisir le jour");
int moissaisi = Entrée.entier("Saisir le mois");
int ansaisi = Entrée.entier("Saisir l'année");
d1.initial (joursaisi, moissaisi, ansaisi);
if(d1.compar () == 1)
System.out.println("La date saisie est supérieure à la date système");
else
if (d1.compar()==0)
System.out.println("La date saisie est égale à la date système");
else
System.out.println("La date saisie est inférieure à la date syst.");
}
}
Code de la classe Prog2date qui utilise MaClasseDate :
import java.io.*;
class Prog2date
{
public static void main (String args[]) throws IOException
{
MaClasseDate d1=new MaClasseDate();
MaClasseDate d2=new MaClasseDate();
// Saisie d'une 1ère date */
int joursaisi = Entrée.entier("Saisir le jour");
int moissaisi = Entrée.entier("Saisir le mois");
int ansaisi = Entrée.entier("Saisir l'année");
d1.initial (joursaisi, moissaisi, ansaisi);
// Saisie d'une 2ème date */
joursaisi = Entrée.entier("\nSaisir le jour");
moissaisi = Entrée.entier("Saisir le mois");
ansaisi = Entrée.entier("Saisir l'année");
d2.initial (joursaisi, moissaisi, ansaisi);
if(d1.compar (d2) == 1)
System.out.println("La 1ère date est supérieure à la 2ème date");
else
if (d1.compar(d2)==0)
System.out.println("Les 2 dates sont égales");
else
System.out.println("La 1ère date est inférieure à la 2ème date");
}
}
Remarque : le JDK offre bien entendu des classes pour manipuler les dates, on n'est pas obligé d'écrire ses propres classes pour traiter les dates comme nous l’avons fait ici à moins qu'on ait des besoins particuliers.