Chapitre 11 Types de données abstrait et mécanismes d'encapsulation ISBN 0-321-49362-1 Chapitre 11 Sujets • • • • • • • Le concept d'abstraction Types de données abstraits Choix de conception Exemples: C++, Java, C# et C Types de données paramétrés Encapsulation Espace de noms 1-2 Le concept d'abstraction • Une abstraction est la représentation d'une entité par ses éléments les plus significatifs • Fondamental en informatique • Abstraction des processus: – Sous programmes • Abstraction des données: – Sujet de ce chapitre 1-3 Type de données abtrait • Type de données satisfaisant les conditions suivantes: – La représentation ainsi que les opérations sont définies à l'intérieur d'une seule unité syntactique. – La représentation des instances (objets) du type est invisible à l'extérieur de l'unité syntactique. • Les seules opérations possibles sont celles explicitement rendues disponibles dans la définition du type. 1-4 Avantages de l'abstraction • Programmes mieux structurés et plus facilement modifiables. • Permet de compiler séparément différentes unités du programme • Fiabilité – La modification de la représentation du type n'a aucune conséquence sur les autres parties qui utilisent le type de données. 1-5 Choix de conception • Forme de l'unité syntactique contenant la définition du type. • Opérations prédéfinies – Affectation – Comparaison • Opérations fréquentes – – – – Itérateurs Accesseurs Constructeurs Destructeurs • Types paramétriques 1-6 Exemples: C++ (1) • Influence des struct en C et des classes en Simula 67 • L'unité syntactique est la classe • Toutes les instances d'une classe partagent un même copie des fonctions membres • Chaque instance d'une classe possède sa propre copie des membres qui sont des variables – sauf pour les variables déclarés statiques (variables de classe) • Les instances peuvent être statiques, dynamique sur pile ou dynamique sur tas 1-7 Exemples: C++ (2) • Protection de l'information – Private: pour cacher l'information – Public: Pour l'interface – Protected clause: Pour l'héritage 1-8 Exemples: C++ (3) • Constructeurs: – Fonction pour initialiser les variables membres une fois l'objet créé – Peut aussi allouer de l'espace si une partie de l'objet est dynamique sur tas – Peut inclure des paramètres – Appelé implicitement lorsque l'objet est créé – Peut aussi être appelé explicitement – Le nom du constructeur est le même que celui de la classe 1-9 Exemples: C++ (4) • Destructeurs – Nettoie l'environnement lorsque l'objet est détruit: libère la mémoire utilisée par l'objet – Appelé implicitement à la fin de la vie de l'objet – Peut être appelé explicitement – Le nom du destructeur est le même que celui de la classe précédé par le symbole ~ 1-10 Exemple: C++ (5) class stack { private: int *stackPtr, maxLen, topPtr; public: stack() { // a constructor stackPtr = new int [100]; maxLen = 99; topPtr = -1; }; ~stack () {delete [] stackPtr;}; void push (int num) {…}; void pop () {…}; int top () {…}; int empty () {…}; } 1-11 Exemples: C++ (6) • Fonctions et classes amies (friend) – Donne accès aux membres privés à d'autres unités syntaxiques – Nécessaire en C++ • Exemple: – classe matrice – classe vecteur – multiplication d'une matrice par un vecteur 1-12 Exemples: Java (1) • Similaire à C++, sauf: – Tous les type définis par l'usager sont des classes – Tous les objets sont alloués sur le tas (on y accède via une variable référence) – On associe explicitement à chaque membre un attribut private, protected ou public (plutôt que de définir des zones private et public) – Java possède un second mécanisme de portée: les packages. • Contient plusieurs classes • Chaque classe a accès aux membres protected des autres classes du même package. • Alternative aux fonctions friend du C++ 1-13 Exemples: Java (2) Accès aux membres selon les modificateurs: sous classe package classe autres Oui Oui Oui Oui protected Oui Oui Oui Non (rien) Oui Oui Non Non private Oui Non Non Non public 1-14 Exemple: Java (3) class StackClass { private int [] stackRef; private int [] maxLen, topIndex; public StackClass() { // a constructor stackRef = new int [100]; maxLen = 99; topPtr = -1; }; public void push (int num) {…}; public void pop () {…}; public int top () {…}; public boolean empty () {…}; } 1-15 Exemples: C# • Influencé par C++ et Java • Toutes les instances de classes sont dynamique sur le tas • Constructeur par défaut • La présence d'un ramasse miettes rend le destructeur moins utile • Les structs sont des classes restreintes ne supportant pas l'héritage. 1-16 Exemples: C# (2) • Méthode d'accès pour accéder aux variables membres d'une classe: – getter et setter • C# contient un mécanisme (les propriétés --properties) facilitant l'implémentation de méthodes d'accès. 1-17 Exemple: C# (3) public class Weather { public int DegreeDays { //** DegreeDays est une propriété get {return degreeDays;} set {degreeDays = value;} } private int degreeDays; ... } ... Weather w = new Weather(); int degreeDaysToday, oldDegreeDays; ... w.DegreeDays = degreeDaysToday; ... oldDegreeDays = w.DegreeDays; 1-18 Exemple: C# (4) Les propriétes permettent: • Créer des variables en lecture seule • Ajouter des contraintes tels que la vérification de bornes avant l'affectation d'une variable. • Modifier l'implémentation des variables membres sans affecter le code client 1-19 Types de données paramétrés • Permet de créer des TDA pouvant contenir des éléments de type arbitraire • Aussi appelé classe générique • Supporté en C++, Ada, et C# 2005 • Supporté partiellement en Java 5.0 (les paramètres générique doivent être des classes). • Inutile dans les langages à typage dynamique comme Python 1-20 Exemple: C++ template <class type> class stack { … stack (int size) { stk_ptr = new type [size]; max_len = size - 1; top = -1; }; … } stack<int> stk(100); 1-21 Exemple: Java • Les premières versions ne supportait pas les types génériques définis par l'usager. • Les conteneurs (LinkedList, ArrayList, etc.) pouvaient contenir n'importe quel type d'éléments (tous de type Object) • Obligé d'utilise une conversion explicite de type. • Depuis la version 5.0, Java supporte les type génériques. 1-22 Mécanisme d'encapsulation • Deux besoins spéciaux pour les grands programmes: – Struturer autrement qu'avec les sousprogrammes – Compilation partielle • Solution: Regroupement de sousprogrammes logiquement reliés en unités de compilation • C'est ce qu'on appelle l'encapsulation 1-23 Encapsulation en C • Les fichiers contiennent un ou plusieurs sous programmes. Ils peuvent être compilés séparément. • L'interface est mise dans un fichier d'en-tête • Problème: L'éditeur de lien ne vérifie pas la cohérence des types entre un fichiers d'en-tête et le fichier contenant l'implémentation. • On utilise le préprocesseur pour inclure le fichier d'en-tête – #include 1-24 Encapsulation en C++ • Similaire à C • Il y a aussi les fonction amies (friend) qui peuvent accéder aux membres privés d'une classe. 1-25 C#: Assemblies • Collection de fichiers apparaissant comme une unique composante (dll ou exe) • Un dll est une collection de classes et de méthodes pouvant être lié dynamiquement en cours d'exécution. • Les assemblies peuvent être: – private: disponible à une seule application – public: disponible à toutes les applications. • C# possède un modificateur appelés internal. Un membre internal n'est visible que dans les classes d'un même assembly. 1-26 Espace de noms • Les grand programmes utilisent beaucoup de noms (classes, fonctions, variables globales, etc.). • Il est nécessaire d'avoir un mécanisme permettant de définir des espaces de noms. • Autre forme d'encapsulation • C++ et C#: – Chaque librairie possède son propre espace de noms 1-27 Espace de nom (2) • Les packages de Java – Peut contenir plus d'une classes – Les classes d'un même package sont des amies (partiel à cause du modificateur private) – Les clients utilisent les noms de classes avec le nom du package ou utilisent la déclaration import 1-28 Sommaire • Importance des TDA • Deux caractéristiques: Unité syntactique unique et protection de l'information. • C++: Utilise les classes • Java et C#: similaire à C++ • Types de données paramétriques • Espace de noms 1-29