Site A.T.L.A.N.T.I.C-83
COURS = Algorithmique (Chapitre_4) - VERSION: 1.0 (M.A.J: 14/04/09)
- AUTEUR(s): Bernard GIACOMONI
Ecran large mobile
Retour
sommaire cours

IV.ANNEXES:


AVERTISSEMENT:

Ce dernier chapitre regroupe des notions qui ne sont généralement pas traitées dans le cadre de l'algorithmique, mais qui ont pourtant une grande importance dans les langages de programmation (notion d'évènement, parallélisme, notiond'objets). Il nous est apparu intéressant de les traiter ici, indépendamment de tout langage de programmation, de façon à faire ressortir les aspects fondamentaux de leur problématique.
D'autre part, les notions qui apparaîssent dans ce chapitre ne font l'objet d'aucune convention d'écriture en algorithmique. De ce fait, des solutions sont proposées pour les noter.


IV.1.ANNEXE I: GESTION D'EVENEMENTS:


IV.1.1.LA NOTION DE FLOT DE CONTRÔLE:


IV.1.1.1.DEFINITION:


En algorithmique, on considère qu'à un instant donné, un processeur peut exécuter un algorithme et un seul. D'autre part, nous avons vu que l'ordre dans lequel un processeur exécute les instructions d'un algorithme était déterminé par:
  • L'ordre défini par la liste d'instructions, lorsqu'il exécute une structure séquencielle.
  • L'état de l'environnement d'exécution, lorsqu'il exécute une structures alternatives ou itérative.
Nous verrons plus loin que d'autres causes sont susceptible d'intervenir.


La suite des instructions parcourues par le processeur peut donc varier d'une exécution à l'autre, en fonction de la réalisation ou non de telle ou telle condition. En particulier, le nombre de répétitions des instructions incluses dans des structures itératives peut varier.


DEFINITION: La suite des instructions parcourues par un processeur lors de l'exécution d'un algorithme est appelée FLOT DE CONTRÔLE.


REMARQUE:

Le flot de contrôle est intuitivement assimilable à la «trace» que laisserait le processus en parcourant les instructions de l'algorithme, ou bien à un «fil d'Ariane» (en anglais, filin = «thread» ...) qu'il suivrait, et sur lequel seraient «fixées» les instructions qu'il exécute.


IV.1.1.2.FLOT DE CONTRÔLE D'UN ALGORITHME ISOLE DE TOUTE INFLUENCE:


En l'absence de toute influence externe à l'algorithme (et en particulier en l'absence d'instruction d'entrée), le flot de contrôle ne dépend que de l'ordre de la liste des instructions de cet algorithme et de l'état de son espace d'exécution au moment de l'exécution de chaque instruction conditionnelle (alternative ou itérative).


DEFINITION: On appelle «état de l'espace d'exécution» à un instant donné l'ensemble des valeurs des contenus des variables de l'espace d'exécution à cet instant.
Dans le cas d'un algorithme isolé, l'état En de l'espace d'exécution après la nieme instruction ne dépend que de l'état En-1 de cet espace avant l'exécution de cette instruction et de la nature de cette nieme instruction. On peut en déduire par récurrence que dans le cas d'un tel algorithme, le flot de contrôle est entièrement prédictible à partir de l'état initial E0 de l'espace d'exécution.


EXEMPLE:


00 DEBUT
01 // Déclaration des données (Espace d'exécution)
02 var A en numerique
03 var B en numerique
04 var R en numerique

05 // Debut procedure
06 A←3
07 B&larr - 2
08 R← A – B
09 SI R < 0 ALORS
10 SORTIR "A est plus petit que B" // Sur l'écran
11 SINON
12 SORTIR "A est plus grand ou égal à B" // Sur l'écran
13 FINSI
14 FIN


Cet algorithme n'inclue aucune opération d'entrée. Le flux de contrôle ne dépend donc que de l'état initial de son espace d'exécution:
  • Ici, cet état est initialisé à A = 3 et B = -2. De ce fait, le flot de contrôle suivra les instructions 5, 6, 7, 8, 9, 12, 13 et 14.
  • Si l'on avait initialisé A et B à 3, le flot de contrôle serait: 5, 6, 7, 8, 9, 10, 11, 13 et 14.


IV.1.1.3.FLOT DE CONTRÔLE D'UN ALGORITHME NON ISOLE DE TOUTE INFLUENCE:


Une influence externe à l'algorithme peut avoir pour effet soit de modifier l'espace d'exécution de l'algorithme, ce qui peut, par le jeux des instructions conditionnelles, amener une modification du flot de contrôle, soit de perturber directement ce même flot de contrôle.


ALGORITHME COMPORTANT UNE INSTRUCTION ENTRER:


La modification de l'espace d'exécution par une influence externe peut être provoquée tout simplement par une instruction ENTRER: dans l'exemple ci-dessus, la valeur de A pourrait être saisie par une instruction ENTRER A au lieu d'être fixée par une affectation. Remarquons que la présence d'une entrée implique l'existence d'un processeur extérieur: la personne ou l'équipement qui fournit les informations d'entrée.
Dans ce cas, à condition que:
  • L'instruction d'entrée puisse être atteinte par le flot de données à partir de l'état initial.
  • Les données acquises aient une influence sur le déroulement du flot de données
Le flot de données ne sera plus entièrement prédictible, puisqu'il dépendra en partie de la valeur acquise.


ALGORITHME INTERAGISSANT PAR DONNEES PARTAGEES AVEC UN AUTRE ALGORITHME:


Il existe un autre cas ou l'on peut envisager la modification de l'espace d'exécution d'un algorithme par une influence extérieure: c'est le cas de l'exécution simultanée (par plusieurs processeurs) de plusieurs algorithmes se partageant le même espace d'exécution. Ce type d'interaction est très souvent utilisé lorsque deux processus travaillant de manière asynchrone l'un de l'autre doivent échanger des données:


EXEMPLE:

Une station de météorologie reçoit toutes les 5 secondes l'information «vitesse du vent», mesurées par un anémomètre. Cette station de météorologie doit fournir à des clients, lorsque ceux-ci le demandent, une des indications suivantes: «vent faible», «vent moyen» ou «vent fort», en fonction de la vitesse du vent calculée par une moyenne glissante. On peut modéliser ce système par deux algorithmes asynchrones l'un de l'autre, s'exécutant en même temps. Le premier algorithme assure l'acquisition de la vitesse du vent et calcule la moyenne glissante (celle-ci consiste ici à prendre 90% de la moyenne précédente et 10% de la valeur courante):


DEBUT
var VitesseVent en numerique
var VitesseMoyenne en numerique
VitesseMoyenne ← 0
TANT QUE ( <La station est en fonction> ) FAIRE
ENTRER VitesseVent // depuis le capteur de température
VitesseMoyenne ← ( VitesseMoyenne * 0,9 ) + ( VitesseVent * 0,1 )
FINFAIRE
FIN


Le deuxième algorithme assure la fourniture de la vitesse moyenne du vent quand un client la demande:


DEBUT
var VitesseMoyenne en numerique
var DemandeClient en chaîne de caractères

TANT QUE ( <La station est en fonction> ) FAIRE
ENTRER DemandeClient
SI DemandeClient = ''Vitesse Vent'' ALORS
SI VitesseMoyenne < 10 ALORS
SORTIR ''vent faible'' // Vers l'écran du client
SINON SI (VitesseMoyenne >= 10) ET < 30) ALORS
SORTIR ''vent moyen'' // Vers l'écran du client
SINON SI VitesseMoyenne > 30 )ALORS
SORTIR ''vent fort'' // Vers l'écran du client
FINSI
FINSI
FINFAIRE
FIN


On voit que le deuxième algorithme a besoin d'échanger la valeur courante de la donnée VitesseMoyenne avec le premier. On pourrait envisager de faire communiquer les deux algorithmes par des opérations d'entrée-sortie, mais cela impliquerait de trouver un point de synchronisation entre les deux algorithmes ou de disposer d'entrées bufferisées. Une solution plus simple consiste à rendre commune une partie des deux espaces d'exécution en déclarant la donnée VitesseMoyenne «donnée partagée» entre les deux algorithmes. On pourra représenter ce fonctionnement par les algorithmes suivants:


DONNEES PARTAGEES
var VitesseMoyenne en numerique
FIN DONNEES PARTAGEES

DEBUT
var VitesseVent en numerique

VitesseMoyenne ← 0
TANT QUE ( <La station est en fonction> ) FAIRE
ENTRER VitesseVent // depuis le capteur de température
VitesseMoyenne ← ( VitesseMoyenne * 0.9 ) + ( VitesseVent * 0,1 )
FINFAIRE
FIN


DEBUT
var DemandeClient en chaîne de caractères

TANT QUE ( <La station est en fonction> ) FAIRE
ENTRER DemandeClient
SI DemandeClient = ''Vitesse Vent'' ALORS
SI VitesseMoyenne < 10 ALORS
SORTIR ''vent faible'' // Vers l'écran du client
SI (VitesseMoyenne >= 10) ET(VitesseMoyenne < 30) ALORS
SORTIR ''vent moyen'' // Vers l'écran du client
SINON SI VitesseMoyenne > 30 )ALORS
SORTIR ''vent fort'' // Vers l'écran du client
FINSI
FINSI
FINSI
FINFAIRE
FIN


On voit que le flot de contrôle du deuxième processeur sera affecté par la valeur de la variable VitesseMoyenne, qui elle-même dépendra de la valeur de la vitesse du vent saisie par le premier algorithme.

REMARQUE:
Les deux algorithmes étant asynchrones, il est possible que parfois ils accèdent en même temps à la donnée VitesseMoyenne. Dans une application informatique, la modification de cette donnée par le premier processus n'est pas instantatée. Sa lecture simultanée par le deuxième peut donc poser des problèmes (la lecture d'une donnée en cours de modification peut aboutir à l'acquisition d'un état transitoire non significatif). Ces problèmes sont résolus par des dispositifs appelés sémaphores. En algorithmique, on négligera cet aspect..


ALGORITHMES TRAITANT DES EVENEMENTS:


Une autre cause de perturbation du flot de contrôle est la prise en compte d'événements. Ce cas sera traité au paragraphe suivant.


IV.1.2.GESTION DES EVENEMENTS:


IV.1.2.1.EVENEMENTS ET SIGNAUX:


DEFINITION:

En informatique, un SIGNAL est un dispositif qui permet de prévenir un processeur de la survenue d'un événement lié à des causes (externes ou internes au processeur), totalement indépendantes du processus en cours d'exécution.


Par exemple, un signal peut prévenir un processeur qu'une touche du clavier a été frappée ou qu'un bouton de la souris a été «cliqué»: la frappe peut être totalement asynchrone du processus en cours. Mais un signal peut aussi être engendré par une cause interne: par exemple, une anomalie de fonctionnement ou la fin d'un délai d'attente programmé sur l'horloge interne.


Prévenir un processeur de la survenue d'un événement n'a pas grande utilité si le processeur n'est pas capable de modifier son flot de contrôle immédiatement pour agir en conséquence. De ce fait, les processeurs informatiques incluent plusieurs mécanismes permettant de prendre en compte les signaux dès leur survenue. Ils peuvent se ranger en deux catégories:
  1. Les instructions de mise en attente du processus
  2. Les mécanismes de traitement des interruptions.


IV.1.2.2.TRAITEMENT SYNCHRONE DES EVENEMENTS - MISE EN ATTENTE DU PROCESSEUR:


Cette technique repose sur l'emploi d'instructions dites «d'attente». Lorsque le processeur rencontre une de ces instructions, il arrète le flot de contrôle sur celle-ci jusqu'à ce qu'il ait reçu le ou les signaux que cette instruction est sensé attendre.
Dès qu'un des signaux attendus survient, le flot de contrôle redémarre en séquence.


DEFINITION:

Une INSTRUCTION D'ATTENTE a pour effet d'arrêter le flot de contrôle jusqu'à la survenue d'un signal. Elle permet donc de synchroniser un flot de contrôle avec l'arrivée de l'événement associé à ce signal.


NOTATION DES INSTRUCTIONS D'ATTENTE:

Les langages informatiques définissent toute une gamme d'instructions d'attente. Certaines sont spécialisées (comme l'instruction delay du langage c sous windows, qui permet d'attendre la survenue d'un signal de fin de décompte envoyé par l'horloge interne), d'autres sont associées avec des structures de données permettant de définir quels signaux sont attendus (par exemple l'instruction sigwaitinfo sous posix 4). En algorithmique, ces instructions pourraient être notées:


ATTENDRE <signal 1> <signal 2> ... <signal n>

On peut aussi définir l'événement comme la fin d'un délais d'attente de n secondes:

ATTENDRE 15 secondes

Dans tous les cas, pendant l'attente, le processeur est libéré. Il peut donc être affecté à l'exécution d'un autre algorithme.


EXEMPLE:
On veut afficher sur un écran, toutes les secondes rondes, l'heure courante:

DEBUT
// Données locales
var HeureCourante en numerique

// Debut procedure
TANT QUE <on veut afficher la date > FAIRE
ATTENDRE <la seconde ronde>
ENTRER HeureCourante // DEPUIS l'horloge interne
SORTIR heureCourante // VERS l'écran
FIN TANT QUE
FIN


REMARQUE:

En algorithmique, une opération ENTRER se comporte implicitement comme une instruction:
ATTENDRE <information a entrer>
En effet: soit l'information est déjà présente au moment ou le processeur l'exécute, et le flot de données continue, soit l'information n'est pas encore présente et on attend l'événement d'arrivée de cette information.


IV.1.2.3.TRAITEMENT ASYNCHRONE DES EVENEMENTS - INTERRUPTIONS:


NOTION D'INTERRUPTION:


Les processeurs informatiques incorporent tous un mécanisme de «traitement d'interruptions» dont voici la description schématique:


DEFINITION:
Le mécanisme d'interruption permet à un processeur d'interrompre provisoirement le flot de données en cours pour aller exécuter un traitement plus urgent, lié à la survenue d'un signal. Ce traitement est appelé souvent «gestionnaire d'interruption»:

Le principe de ce mécanisme est le suivant:
  1. Supposons que le processeur soit en train d'exécuter l'algorithme A1.
  2. Supposons alors qu'à un instant donné, pendant que le processeur exécute l'instruction In de cet algorithme, un événement (signal) survienne. Le mécanisme d'interruption déroute alors, à la fin de l'exécution de In, le flot de contrôle vers un algorithme A2, qui dépend de l'événement reçu. Simultanément, le contexte d'exécution de l'algorithme A1 est sauvegardé.
  3. Le processeur exécute alors l'algorithme A2 qui contient les traitements spécifiques à cette interruption.
  4. A la fin de l'algorithme A2, le flot de contrôle est redirigé vers l'endroit oû il a été interrompu dans l'algorithme A1, c'est à dire après l'instruction In. Le contexte d'exécution sauvegardé à l'étape 2 est remis en place.



ANALOGIE:

  • Un employé administratif est à son bureau, en train de traiter à son rythme des dossiers en attente (Algorithme A1)
  • Le téléphone sonne.
  • L'employé interromp le fil de son travail (son flot de contrôle) pour répondre au téléphone. Ce faisant, il va essayer de sauver son contexte d'exécution (par exemple, il va repérer la page du dossier qu'il est en train de consulter).
  • Il va alors prendre en compte l'appel et essayer de satisfaire son interlocuteur, ce qui va l'amener à effectuer un certain nombre d'actions sans rapport avec son activité courante (algorithme A2).
  • Lorsqu'il aura terminé de traiter l'appel téléphonique, il reviendra à son travail courant: pour cela, il rétablira son contexte d'exécution en réouvrant le dossier en cours à la page dont le numéro a été repéré.


REMARQUES:

  • Lorsqu'un processeur accepte le traitement d'interruptions, le flot de contrôle peut devenir totalement imprévisible. En effet, le gestionnaire d'interruptions peut modifier l'espace d'exécution de l'algorithme A1 (par exemple en effectuant une instruction ENTRER).
  • Un gestionnaire d'événement peut être lui-même interrompu par un événement de priorité supérieure.


DEFINITION D'UN GESTIONNAIRE D'INTERRUPTION:


En algorithmique, on pourra définir un gestionnaire d'interruption par l'instruction suivante:


QUAND <signal> FAIRE <Nom de fonction>


EXEMPLE D'UTILISATION D'UN GESTIONNAIRE D'INTERRUPTIONS:


Supposons que sur un écran d'ordinateur, nous ayons ouvert deux fenêtres: dans la fenêtre numéro 1, nous voulons éditer un texte, alors que dans la fenêtre numéro 2 nous voulons afficher l'heure courante toutes les secondes, avec moins d'une seconde d'imprécision. Ce fonctionnement pourrait être décrit de la manière suivante:


DEBUT
// Données locales:
var NomFichierTexte en chaine de caracteres
var CommandeTexte en chaine de caracteres
var TexteSelectionne en chaine de caractere

// Debut procedure Traitement_de_Texte:
<Affichage de l'éditeur de texte dans la fenêtre n° 1>
<Affichage de l'horloge dans la fenêtre n° 2>
QUAND <Signal seconde ronde> FAIRE AfficherDate
TANT QUE <on veut éditer le texte> FAIRE
ATTENDRE <Saisie d'une commande d'édition de texte>
ENTRER CommandeTexte // DEPUIS Fenêtre n° 1
SUIVANT LE CAS CommandeTexte FAIRE
CAS Ouvrir:
<Afficher la liste des fichiers du répertoire courant>
ATTENDRE <Clic souris bouton gauche>
<récupérer le nom du fichier cliqué dans NomFichierTexte>
<Ouvrir le fichier NomFichierTexte et l'afficher dans la fenêtre n°1>
................................
................................
CAS Inserer:
<inserer du texte à l'emplacement du curseur>
CAS Copier:
lt;Copier le texte sélectionné dans TexteSelectionné>
................................
................................
AUTRES CAS:
SORTIR «Commande inconnue» // Vers Fenêtre 1
FINCAS
FIN TANT QUE
FIN

FONCTION AFFICHER_DATE
var DateCourante en numerique

ENTRER DateCourante // DEPUIS l'horloge interne
SORTIR DateCourante // VERS Fenêtre 2
FIN FONCTION


Nous voyons ici que l'algorithme principal supporte l'éditeur de texte: après avoir affiché les menus des applications «traitement de texte» et «horloge» dans les fenêtres et installé le gestionnaire d'événement AfficherDate associé au signal de survenue d'une seconde ronde, il entre dans une boucle de scrutation des commandes sélectionnées par l'utilisateur de l'éditeur de texte.
Lorsque l'événement «seconde ronde» survient, quelle que soit l'instruction en cours, le processeur se déroute vers la fonction AfficherDate: il va alors acquérir la date courante et l'afficher dans la fenêtre n° 2, puis revenir exécuter l'algorithme principal au point où il l'avait quitté.
Dans cet exemple, le traitement de l'affichage par un gestionnaire d'interruption s'impose car l'algorithme principal comporte déjà une attente des commandes de traitement de texte, dont la survenue dépend de l'utilisateur: plusieurs dizaines de secondes peuvent s'écouler entre deux commandes, pendant lesquelles le flot de commandes serait bloqué sur cette attente. Il est donc impossible d'utiliser une autre attente pour détecter le signal «seconde ronde».
L'utilisation d'un gestionnaire d'interruptions permet donc de garantir que l'affichage de l'heure se fera toutes les secondes, quel que soit le comportement de l'utilisateur de l'éditeur de texte.


IV.2.ANNEXE II: LA NOTION D'OBJET:


IV.2.1.GENERALITES:


La notion d'objet dérive à la fois de la notion de procédure et de la notion de structure. Elle résulte de la volonté de rassembler en une même entité les traitements et les données sur lesquelles ces traitements travaillent, de façon à cacher à l'utilisateur le détail de ces traitements (encapsulation);


Un objet est donc une structure de données qui contient à la fois des variables et des procédures de traitement de ces variables.


IV.2.2.ATTRIBUTS ET METHODES:


L'exemple suivant représente un objet appelé DOCUMENT:



IV.2.2.1.LES ATTRIBUTS:


Nous voyons que l'objet DOCUMENT encapsule des données, que l'on appelle également «ATTRIBUTS» de l'objet.
  • Par défaut, un attribut est accessible pour toutes les procédures internes de l'objet (c'est une donnée GLOBALE de l'objet) et non accessible de l'extérieur de l'objet.
  • Ces attributs peuvent être rendues accessibles de l'extérieur de l'objet. On dit alors qu'ils sont PUBLICS. Sinon, ils sont dits PRIVES.


L'accès à un attribut public depuis un algorithme externe à l'objet se fait de la manière suivante:
<Nom d'objet>.<Nom d'attribut>

EXEMPLE: Accès à l'attribut Selection: DOCUMENT.Selection


REMARQUE:


Nous voyons que le mode d'accès à un attribut d'un objet est identique au mode d'accès d'un élément d'une structure.


IV.2.2.2.LES METHODES:


Cet objet encapsule d'autre part un certain nombre de procédures. Ces procédures sont appelées «METHODES». Les méthodes sous des procédures qui peuvent être activées de l'extérieur de l'objet. Elles ont accès à tous les attributs de cet objet.


On accède à une méthode depuis un algorithme externe à l'objet de la même manière que pour un attribut:


<Nom d'objet>.<Nom de la méthode> ( <liste d'arguments> )

EXEMPLE: Accès à la méthode InsererTexte: DOCUMENT.InsererTexte ( <Texte> )


IV.2.2.3.LA DEMARCHE D'ENCAPSULATION:


Revenons à l'exemple précédent. L'objet document renferme un attribut appelé Texte, qui représente le texte d'un document. Il offre d'autre part au «monde extérieur» un certain nombre de méthodes qui permettent de travailler sur ce document. On peut ainsi:
  • Afficher le texte
  • Déplacer un curseur dans le texte
  • Insérer du texte à l'emplacement du curseur
  • Sélectionner une partie du texte
  • Copier la sélection
  • Couper la sélection
  • Réafficher le texte
  • etc...


L'objet se présente donc comme une interface permettant d'éditer un document. L'objet permet de faire abstraction de la complexité des opérations listées ci-dessus pour ne s'occuper que de leur résultat. Cette démarche par encapsulation représente une des caractéristiques principales de la conception par objets.


IV.2.3.NOTIONS DE CLASSE D'OBJETS ET D'INSTANCIATION:


IV.2.3.1.DEFINITION:


Un deuxième aspect de la conception par objets est la notion de «CLASSE» d'objets. Nous avons vu que la notion d'objet présente certaines similitudes avec la notion de structure. Il s'agit en fait d'une structure particulière qui encapsule non seulement des données (les attributs), mais aussi du code exécutable (les méthodes).
De ce fait, de la même façon qu'un TYPE STRUCTURE, une fois défini, peut être utilisé comme modèle pour déclarer des structures de même type, un objet peut être considéré comme un modèle, pouvant servir à déclarer d'autres objets de même type.

VOCABULAIRE:
  • Un objet ainsi utilisé comme modèle sera appelé CLASSE d'objets.
  • L'action de déclarer un objet à partir d'une CLASSE se dit: «INSTANCIER» cette classe (c'est à dire créer une instance, une copie de cette classe).


IV.2.3.2.DECLARATION D'UNE CLASSE:


La plupart des langages de programmation utilisent pour déclarer une classe un schéma syntaxique proche de ce qui suit:
CLASSE <Nom de classe>
<Déclaration des attributs>
<Déclaration des méthodes>
FIN CLASSE


EXEMPLE:

CLASSE Document
// Déclaration des attributs:
var Texte en chaîne de caractères
var DateModification en numerique

// Déclaration des méthodes:
// - Méthode InsererTexte
PROCEDURE InsererTexte ( var Texte_a_Ajouter en chaîne de caractères )
....................................
....................................
....................................
FIN PROCEDURE

// - Méthode PositionnerCurseur
PROCEDURE positionnerCurseur ( var X en numerique, var Y en numerique )
....................................
....................................
....................................
FIN PROCEDURE
etc...
FIN CLASSE


IV.2.3.3.INSTANCIATION D'UNE CLASSE:


La plupart des langages de programmation utilisent pour déclarer une classe un schéma syntaxique proche de ce qui suit:


OBJET <nom du nouvel objet> = NOUVEAU <nom de la classe d'objet>

EXEMPLE:
OBJET MonDocument = NOUVEAU Document // crée un objet «MonDocument» sur le modèle de la classe Document.


REMARQUE:Dans la plupart des langages de programmation, l'opérateur d'instanciation est représenté par le mot-clef «new»


IV.2.3.4.CONSTRUCTEURS ET DESTRUCTEURS:


Dans le cas d'un langage de programmation, l'opérateur new déclanche l'exécution d'une méthode particulière de la classe appelée CONSTRUCTEUR, et dont une caractéristique est d'avoir le même nom que la classe. Cette méthode est ajoutée automatiquement à toute classe. Elle n'a donc pas besoin d'être déclarée.

Cependant, dans le cas ou le constructeur n'est pas déclaré (constructeur implicite), sa seule fonction est de réserver en mémoire un espace équivalent à un objet de la classe et de définir un pointeur d'accès à cet espace: cette fonction n'a évidemment aucune utilité en algorithmique. En revanche, il est possible de déclarer un constructeur comme toute autre méthode, ce qui permet d'y inclure des traitements d'initialisation de l'objet.

EXEMPLE: si l'on définit une classe Arbre comportant les attributs TypeArbre et AgeArbre, il peut être intéressant de définir la méthode constructeur de la manière suivante:


PROCEDURE Arbre ( Type en chaîne de caractères, Age en numérique )
TypeArbre ← Type
AgeArbre ← Age
FIN PROCEDURE


Ce constructeur permettra de créer des objets Arbre en initialisant leurs attributs:
MonArbre = NOUVEAU Arbre ( "platane", 10 ) crée un platane de 10 ans. La notion de constructeur peut donc avoir son utilité en algorithmique pour personnaliser les objets à la création.

En ce qui concerne les DESTRUCTEURS, ce sont des méthodes implicites qui sont appelés lorsqu'on détruit un objet (Opérande DELETE), ce qui entraîne la désallocation de ses ressources (en particulier, sa zone mémoire est libérée). Les destructeurs n'ont pas d'utilité en algorithmique.


IV.2.3.5.ACCÈS À UN ATTRIBUT OU À UNE MÉTHODE:


L'accès à un attribut ou à une méthode suit en général la même syntaxe que l'accès à un membre d'une structure:
  • MonDocument.DateModification // Donne accès à l'attribut DateModification de l'objet MonDocument.
  • MonDocument.AjouterTxt (...) // Permet d'activer la méthode AjouterTxt de l'objet MonDocument.


ATTENTION:

on voit ici qu'on accède à l'objet MonDocument et non à la classe DOCUMENT: en effet, comme dans le cas d'une structure, seul un OBJET a une existance réelle. Une CLASSE n'est qu'un type d'objet, un modèle abstrait: il est impossible de charger une donnée dans un attribut ou d'appeler une méthode d'une classe avant que cette classe ait été instanciée par la déclaration d'un objet de cette classe.


IV.2.4.NOTION D'HERITAGE:


IV.2.4.1.DEFINITION:


Le mécanisme de l'HERITAGE permet de construire une classe à partir d'une ou de plusieurs autres classes. Lors d'un héritage, la classe héritière hérite des attributs et méthodes de la classe «donatrice» (ou des classes donatrices). Lorsqu'une classe hérite d'une seule classe, l'héritage est dit «simple», sinon il est dit «multiple».
Les langages informatiques emploient souvent les termes de «classe DERIVEE» et «classe DE BASE» pour désigner respctivement une classe «héritière» et une classe «donatrice». Par la suite, nous utiliserons ces termes.


IV.2.4.2.DECLARATION D'UNE CLASSE DERIVEE:


  • Lors de la déclaration d'une classe par le mécanisme de dérivation, il est possible de doter cette nouvelle classe (outre les attributs et les méthodes héritées de ses classes de base) de nouveaux attributs ou de nouvelles méthodes.
  • Il est également possible de remplacer les méthodes héritées par des méthodes de même nom, mais dont l'algorithmique interne ou les arguments d'appel sont différents. Ce mécanisme est appelé «surcharge» de méthode.


La dérivation permet donc un enrichissement ou une spécialisation de la ou des classes de base.


REMARQUE: Dans la plupart des langages objets, lorsqu'une classe dérivée ne déclare pas explicitement de constructeur, son constructeur implicite fait appel aux constructeurs des classes de base. C'est ce comportement que nous supposerons ici.


IV.2.4.3.SYNTAXE DE DECLARATION D'UNE CLASSE DERIVEE:


Nous proposons la syntaxe suivante (tirée du langage C++):

CLASSE <Nom classe dérivée>: <Nom classe de base 1>,... ,<Nom classe de base n>
<déclaration des attributs spécifiques de la classe dérivée>
<déclaration des méthodes spécifiques ou surcharges des méthodes héritées>
FIN CLASSE


IV.2.4.4.EXEMPLE DE DERIVATION DE CLASSES:


Supposons que, comme dans le premier exemple, nous voulions concevoir une classe permettant d'éditer un texte et supposons que nous disposions déjà de deux classes. La classe Afficheur et la classe SaisieTexte, dont voici les déclarations:

CLASSE Afficheur
var Texte en chaîne de caractères // attribut Texte

Procedure AfficherTexte ()
SORTIR Texte
FinProcedure
FIN CLASSE

CLASSE SaisieTextevar Texte en chaîne de caractères
Procedure InsérerTexte ( var NouveauTexte en chaîne de caracteres )
Texte ← NouveauTexte
FinProcedure

Procedure EffacerTexte ()
Texte ← <Chaîne vide>
FinProcedure
FIN CLASSE


Une classe qui hériterait de ces deux classes serait capable de saisir un texte et de l'afficher, ce qui constitue une partie du comportement d'un éditeur. Créons une classe dérivée de ces deux classes (nous l'appellerons «EditeurSimple»):

CLASSE EditeurSimple: Afficheur, SaisieTexte
var DateModification en numerique

Procedure InsérerTexte ( var NouveauTexte en chaîne de caracteres )
Texte ← NouveauTexte
DateModification ← < Date courante >
FinProcedure
FIN CLASSE


Cette nouvelle classe héritera des attributs et méthodes des deux classes de base. D'autre part, elle possède un nouvel attribut (DateModification) et la méthode InsererTexte est surchargée. En effet, son algorithme interne a été modifié pour intégrer la sauvegarde de la date courante dans l'attribut DateModification lors de l'insertion d'un texte.
La nouvelle classe possèdera donc les attributs Texte et dateModification et les méthodes AfficherTexte, InsererTexte et EffacerTexte. D'autre part, la méthode InsererTexte a été surchargée.


Par instanciation de EditeurSimple (OBJET MonEditeurSimple = NOUVEAU EditeurSimple), nous aurons accès uniquement aux méthodes:
  • MonEditeurSimple.InsererTexte ();
  • MonEditeurSimple.AfficherTexte();
  • MonEditeurSimple.EffacerTexte();

Pour créer un éditeur complet, il va falloir rajouter un certain nombre de comportements (sélectionner, copier, coller) et des attributs permettant de repérer et modifier la position du curseur et de sélectionner une partie du texte. On obtiendra une nouvelle classe EditeurComplet en effectuant:
  • Une dérivation de la classe EditeurSimple
  • L'ajout des attributs Selection, X_PositionCurseur et Y_PositionCurseur
  • L'ajout des méthodes PositionnerCurseur, SelectionnerTexte, CopierSelection, CouperSelection, CollerSelection
  • Une nouvelle surcharge de la méthode InsererTexte pour permettre d'insérer une chaîne de caractères à un endroit donné du texte.
La déclaration de EditeurComplet sera semblable à ce qui suit:

CLASSE EditeurComplet: EditeurSimple

// Attributs ajoutés:
// -------------------------
var Selection en chaîne de caractères
var X_PositionCurseur en numerique
var Y_PositionCurseur en numerique

// Procedures surchargées
// -------------------------

Procedure InsérerTexte ( var NouveauTexte en chaîne de caracteres )
var Rang en numerique

<calcul du rang du caractère pointé par le curseur dans la chaine texte>
Texte (Rang) ← NouveauTexte
DateModification ← < Date courante >

FinProcedure

// Procedures ajouté
// --------------------

Procedure PositionnerCurseur ()
...........................
FinProcedure

Procedure SélectionnerTexte ()
...........................
FinProcedure

Procedure CopierSelection
...........................
FinProcedure

Procedure CouperSelection ( .....)
...........................
FinProcedure

Procedure CollerSelection ( .....)
...........................
FinProcedure

Procedure AfficherTexte ( .....)
...........................
FinProcedure
FIN CLASSE


IV.2.5.CONCLUSION SUR LA CONCEPTION PAR OBJETS:


Nous n'avons abordé ici que les notions de base de la conception et de la programmation par objets. Nous avons essayé de présenter les mécanismes d'une façon la plus indépendante possible des langages de programmation existants, de façon à nous concentrer sur leur logique propre. Cependant, dans le cadre de l'algorithmique, il est impossible d'aborder certains de leurs aspects, car ils sont liés à leur implémentation sur les systèmes informatiques.
Le fait de prendre en compte les mécanismes du monde «objets» en algorithmique a l'avantage de permettre l'utilisation de cette discipline dès la phase de conception détaillée d'une démarche objets.
D'autre part, le mécanisme de l'héritage permet de constituer des arborescences de classes dérivées les unes des autres. Associé au mécanisme d'instanciation des classes, il autorise un très haut niveau de réutilisation des codes qui permet de rationaliser et minimiser l'effort de production. Cet aspect peut être utilisé en algorithmique.


IV.3.ANNEXE III: LES TYPES DE DONNEES EN PROGRAMMATION:


En algorithmique, aucune contrainte de taille mémoire ne pèse sur le développeur. Celui-ci peut donc négliger cet aspect lorsqu'il déclare des données.

Dans un programme informatique, en revanche, la taille des données déclarées peut revètir une grande importance: lorsque l'on déclare un tableau de 1000000 de nombres, le fait que chaque nombre occupe 2 ou 8 octets n'est évidemment pas sans conséquence.

Il est donc nécessaire de disposer de beaucoup plus de types numériques prédéfinis. Pour cela, on distinguera deux types principaux:
  • Les nombres ENTIERS (INTEGER en anglais)
  • Les nombres dits "FLOTTANTS" (FLOAT en anglais), qui correspondent aux nombres non entiers, c'est à dire comportant une partie décimale.
REMARQUE:
l'appellation FLOTTANT (ou FLOAT) fait référence au procédé de codage binaire utilisé pour ces nombres: la position de la virgule (appeléée "caractéristique") y est codée dans un champ binaire distinct de celui des bits "significatifs" (appelé "mantisse").

Puis, on subdivisera ces types en fonction de la capacité de la donnée (valeur maximale codable) et de la prise en compte ou non des valeurs négatives. Le tableau suivant résume cette démarche:


TYPE PREDEFINI LONGUEUR EN OCTETS CAPACITE MAXIMALE
UNSIGNED BYTE (octet non signé) 1 (soit 8 bits) De 0 à 255
BYTE (octet signé) 1 (soit 8 bits) De -128 à +127
UNSIGNED INT («integer» ou entier simple non signé) 2 (Soit 16 bits) De 0 à 65535
INT ( «integer» ou entier simple signé) 2 (Soit 16 bits) De -32768 à +32767
UNSIGNED LONG INT (entier long non signé) 4 (Soit 32 bits) De 0 à 4294966295
LONG INT (entier long signé) 4 (Soit 32 bits) De -2147483648 à +2147483647
FLOAT (Flottant court) 4 (Soit 32 bits), 3 octets pour la valeur et un pour la position de la virgule) Infinie...
DOUBLE FLOAT (Flottant double) 8 (Soit 64 bits), 7 octets pour la valeur et un pour la position de la virgule) Infinie...





Retour accès aux cours Retour sommaire cours