Types de données abstrait et mécanismes d'encapsulation Chapitre 11 Types de données abstrait et mécanismes d'encapsulation
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 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
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.
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.
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
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
Exemples: C++ (2) Protection de l'information Private: pour cacher l'information Public: Pour l'interface Protected clause: Pour l'héritage
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
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 ~
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 () {…}; }
Exemples: C++ (6) Fonctions et classes amies (friend) Exemple: 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
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++
Exemples: Java (2) Accès aux membres selon les modificateurs: classe package sous classe autres public Oui protected Non (rien) private
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 () {…}; }
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.
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.
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;
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
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
Exemple: C++ stack (int size) { stack<int> stk(100); template <class type> class stack { … stack (int size) { stk_ptr = new type [size]; max_len = size - 1; top = -1; }; } stack<int> stk(100);
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.
Mécanisme d'encapsulation Deux besoins spéciaux pour les grands programmes: Struturer autrement qu'avec les sous- programmes Compilation partielle Solution: Regroupement de sous- programmes logiquement reliés en unités de compilation C'est ce qu'on appelle l'encapsulation
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
Encapsulation en C++ Similaire à C Il y a aussi les fonction amies (friend) qui peuvent accéder aux membres privés d'une classe.
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.
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
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
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