Nous abordons aujourd'hui un volet très
important de votre apprentissage de la
programmation.
La programmation dite orien...
En programmation procédurale, j'aurais
tendance à procéder de cette façon,
donc je vais commencer par déclarer une
var...
c'est bien la surface
d'un rectangle que je souhaite calculer.
Donc le fait de pouvoir regrouper en une
seule et même ent...
Commençons par la notion d'encapsulation.
Ce que l'on entend par encapsulation,
c'est
le fait de pouvoir regrouper dans u...
qu'au lieu de
passer au premier appel de surface non pas
hauteur un, mais
hauteur deux, je perds la cohérence de mes
donn...
Au niveau de l'utilisation, je ne vois
désormais du
rectangle que ce que l'on appelle en
jargon orienté objet
son interf...
C'est un niveau interne qui n'est pas
forcément utile à celui qui utilise le
rectangle.
Donc en programmation orientée o...
objets que en
tant qu'utilisateur externe, je ne vois
plus que en
tant qu'objets manipulables au travers de
leur interface...
un rectangle.
Ici le lien entre les données et les
traitements ne se fait
que par le biais du passage des arguments
ce qu...
Les attributs, de par le fait qu'il faut
faire
des choix quant à leur modélisation, des
choix techniques,
des choix d'imp...
ce nouveau type puis va le faire
évidemment en écrivant
un programme qui contient le code de cette
classe rectangle.
Cel...
Prochain SlideShare
Chargement dans…5
×

introduction introdaction introduction introdaction introduction introdaction

861 vues

Publié le

introduction introdaction introduction introdaction introduction introdaction

Publié dans : Économie & finance
0 commentaire
0 j’aime
Statistiques
Remarques
  • Soyez le premier à commenter

  • Soyez le premier à aimer ceci

Aucun téléchargement
Vues
Nombre de vues
861
Sur SlideShare
0
Issues des intégrations
0
Intégrations
4
Actions
Partages
0
Téléchargements
2
Commentaires
0
J’aime
0
Intégrations 0
Aucune incorporation

Aucune remarque pour cette diapositive

introduction introdaction introduction introdaction introduction introdaction

  1. 1. Nous abordons aujourd'hui un volet très important de votre apprentissage de la programmation. La programmation dite orientée objet. Il s'agit d'une façon particulière de programmer, qui n'est d'ailleurs pas spécifique au language C++, et qui va donner à vos programmes un certain nombre de propriétés intéressantes en terme de maintenabilité et de modularité. À ce stade du cours, vous êtes censés connaître un certain nombre d'éléments fondamentaux relatifs à la programmation tout court. Vous savez par exemple exprimer traitements en utilisant des structures de contrôle, comme par exemple des boucles conditionnelles, vous savez aussi structurer un minimum vos données, en utilisant par exemple des tableaux, et vous savez surtout modulariser vos programmes en utilisant la notion centrale de fonction. Cet outillage de base va vous permettre d'exercer un style de programmation particulier dite programmation procédurale, ou impérative, qui a la particularité de faire en sorte que les données et les traitements apparaissent de façon séparée dans un programme. Certes, il y a une interaction entre les deux. Les traitements opèrent typiquement sur les données, lesquelles influencent à leur tour les traitements, mais les deux entités apparaissent de façon séparée. par exemple, comme nous allons le voir dans quelques minutes dans un exemple concret, les traitements peuvent s'exprimer par le biais de fonction, et le lien entre données et traitements peut se faire alors par le biais du passage des arguments, les données manipulées apparaissent au travers d'entités distinctes, comme par exemple les variables. Une des particularités fondamentales de l'orienté objet est de permettre le regroupement des traitements et des données en une seule et même entités. Partons d'un exemple concret. Imaginons que je souhaite écrire un petit programme C++ qui calcule la surface d'un rectangle. Le rectangle est représenté au moyen d'une largeur et d'une hauteur, et je souhaite donc en calculer la surface.
  2. 2. En programmation procédurale, j'aurais tendance à procéder de cette façon, donc je vais commencer par déclarer une variable, la largeur, pour représenter la larguer du rectangle, que j'initialiserai avec une valeur appropriée, et je vais faire de même pour la hauteur. Ensuite, le calcule de surface peut se faire en passant la largeur et la hauteur ainsi définies à une fonction surface, qui se charge de réaliser le calcul approprié. Alors on voit bien au travers de cet exemple que dans un tel programme, les données et les traitements apparaissent de façon séparée. Les variables me permettent de stocker et de modéliser les données dont j'ai besoin, et les traitements sont réalisés par le biais de fonction. Il n'existe pas de lien direct entre les données et les traitements. Le lien s'établit uniquement ici par le biais du passage des arguments. Alors une des critiques fondamentales que l'on peut émettresur ce genre de programmes est l'absence de lien sémentique entre les différentes entités. Par exemple, le lien sémentique qui unit la largeur et la hauteur, il s'agit de la largeur et de la hauteur d'un rectangle, est difficile à établir. Imaginons par exemple que je ne soit pas francophone, et donc que pour moi largeur et hauteur soient des noms peu parlants, il est difficile pour moi de voir qu'il s'agit de deux entités liées à un même concept, celui de rectangle. Alors le lien sémentique qui unit ici les données entre elles n'est pas explicite. Mais il en va de même pour le lien qui unit les données et les traitements qui agissent sur ces données. Imaginons que je sois un petit peu moins précautionneuse dans le choix de mes identificateurs, et que j'appelle cette fonction produit, par exemple. De même, imaginez que j'appelle mes arguments, que je leur donne des noms moins parlants, du coup, il devient très difficile, pour quelqu'un qui lit le code, de voir que l'on est effectivement ici en train de faire un calcul de surface sur un rectangle. Or ce lien existe conceptuellement. Ici c'est bel et bien la largeur et la hauteur d'un rectangle que je suis en train de manipuler, et ici
  3. 3. c'est bien la surface d'un rectangle que je souhaite calculer. Donc le fait de pouvoir regrouper en une seule et même entité la notion de rectangle les données caractéristiques du rectangle, comme sa largeur et sa hauteur, ainsi que les traitements qui lui sont spécifiquement associés, va me permettre d'établir un lien explicite entre ces différentes entités et de donner beaucoup plus de clarté à mon programme. Il s'agit là de l'un des fondamentaux de la programmation orientée objet. Ce qu'il faut savoir de façon globale, c'est que la programmation orientée objet va vous donner un certain nombre d'outillage permettant davantage de robustesse, de modularité, de lisibilité, à vos programmes. Ce qui va dans le sens d'une meilleure maintenabilité. Alors robustesse par rapport aux changements, si votre programme est amené à changer un jour, à être étendu, on ne veut pas être dans l'obligation de tout réécrire, et de robustesse face aux erreurs de manipulation, par exemple, des données. En effet, la plupart des applications développées de nos jours ne sont pas redéveloppées depuis zéro mais consistent à étendre, à maintenir du code existant, et il est important de pouvoir le faire à moindre coût. Nous allons voir que les propriétés fondamentales de l'orienté objet, à savoir davantage de robustesse, de modularité et de lisibilité vont exactement dans ce sens-là . La programmation orientée objet offre en réalité quatre concepts centraux: encapsulation, abstraction, héritage et polymorphisme, qui permettent de mieux organiser les programmes dans le sens de la robustesse, lisibilité, modularité, et maintenabilité, comme je l'ai expliqué tout à l'heure, et ces concepts centraux, ne sont pas spécifiques à un language il s'agit des concepts centraux de l'orienté objet. Dans la séquence présente nous allons essentiellement nous occuper de définir encapsulation et abstraction, et nous aborderons dans les séquences suivantes les notions fondamentales d'héritage et de polymorphisme.
  4. 4. Commençons par la notion d'encapsulation. Ce que l'on entend par encapsulation, c'est le fait de pouvoir regrouper dans une seule et même entité des données et des traitements qui agissent sur ces données. Donc typiquement, dans l'exemple du rectangle, nous allons regrouper dans une seule et même entité la largeur et la hauteur qui caractérisent la représentation du rectangle et la fonctionnalité du calcul de surface. Donc en terme de jargon, on va parler pour les données de la notion d'attributs, et on va parler pour les fonctionnalités de la notion de méthodes. Donc, en programmation orientée objet, on va être dans la possibilité de définir des nouveaux types de données, au travers, nous allons le voir un petit peu plus tard, de la notion de classe, ces types de données peuvent être utilisés pour travailler concrètement avec des données, de types plus abstraits, le rectangle, et ces données vont être des objets qui vont cohabiter dans le programme et interagir dans le programme. Un programme orienté objet va donc typiquement travailler avec des objets, qui sont caractérisés par leurs attributs, et leurs méthodes. Parlons maintenant de la notion d'abstraction. Supposons que je souhaite écrire un programme qui manipule plusieurs rectangles, pas uniquement un seul. Donc dans une approche procédurale, j'aurai typiquement l'occasion de déclarer autant de largeurs et de heuteurs que j'ai de rectangles, ici je l'ai fait pour le premier rectangle, et je devrai bien évidemment faire la même chose pour le second rectangle, ce qui est relativement fastidieux. Si je souhaite maintenant calculer la surface de ces deux rectangles, je vais devoir appeler la fonction surface, lui fournissant comme argument la largeur et la hauteur de chacun des rectangles de façon appropriée, donc je fais un appel à la fonction surface, en lui fournissant à chaque fois les bons arguments. Donc il faut être précautionneux, ceci est source d'erreur. Imaginez par exemple que je me trompe et
  5. 5. qu'au lieu de passer au premier appel de surface non pas hauteur un, mais hauteur deux, je perds la cohérence de mes données, je ne suis plus en train de travailler avec des données d'un même rectangle. Le processus d'abstraction est le processus au terme duquel je réalise que je manipule en réalité les données d'un plus haut niveau, la notion de rectangle, à laquelle je peux associer une notion générique, ici tous les rectangles sont caractérisés par une largeur, et une hauteur, auxquelles on peut attacher un même calcul de surface, du coup je décide de travailler avec la notion plus abstraite de rectangle, plutôt que de travailler avec une description intime de la représentation des rectangles, ce qui nous permet de nous focaliser sur l'essentiel et de cacher les détails. L'encapsulation, qui me permet de regrouper en une seule et même entité des données comme une largeur et une hauteur, et des traitements comme un calcul de surface, est l'outil qui me permet d'aboutir à une vision plus abstraite des objets que je manipule. Du coup je vais permettre à mon programme de désormais pouvoir travailler avec des entités plus abstraites. je vais travailler avec un premier rectangle et un deuxième rectangle, tous les deux de type rectangle dans le programme, je vais invoquer des calculs de surface sur ces rectangles, on va voir qu'en orienté objet, j'anticipe un petit peu sur la suite, que, on va dire, je calcule la surface du premier rectangle, donc on va voir par la suite comment tout ceci s'exprime de façon beaucoup plus précise, et du coup je permets à mon programme de se focaliser sur l'essentiel, Donc je ne suis plus en train de me préoccuper du fait qu'un rectangle est constitué d'une largeur et d'une hauteur. Je me focalise sur les aspects essentiels. Je travaille avec des rectangles. Je fais un calcul de surface sur un rectangle.
  6. 6. Au niveau de l'utilisation, je ne vois désormais du rectangle que ce que l'on appelle en jargon orienté objet son interface d'utilisation c'est-à -dire les fonctionnalités qui sont offertes pour la manipulation du rectangle comme ici le calcul de surface. Faisons une analogie avec un objet de la vie courante. Lorsque vous conduisez votre voiture vous n'avez typiquement besoin d'en connaître que l'interface d'utilisation, concrètement. Eh bien, vous avez besoin d'avoir un volant, un accélérateur, une pédale de frein et à nul moment il ne vous est utile de savoir comment le moteur est concrètement construit. Donc, pour conduire votre voiture, vous n'avez besoin d'en connaître que l'interface d'utilisation. C'est exactement le même principe en programmation orientée objet. Pour utiliser un nouveau type d'objet, une nouvelle classe, vous n'avez besoin d'en connaître que l'interface d'utilisation qui est prévue par le programmeur de la classe. Le reste est du détail d'implémentation interne qu'il n'est pas utile de connaître. Il y a donc deux niveaux de perception d'un objet. Un niveau externe qui est utile au programmeur utilisateur, celui qui utilise la notion de rectangle, dans un programme. Donc il existe désormais un type rectangle. Je peux déclarer des variables de type rectangle, les initialiser de façon appropriée. Et ensuite, ce qui m'intéresse en tant que programmeur utilisateur, c'est les fonctionnalités utiles: le calcul de surface. Donc ce niveau externe est le niveau qui intéresse le programmeur utilisateur, celui qui utilise le type rectangle. Second niveau. Le niveau interne, celui qui a programmé le nouveau type, le type rectangle, a dû se préoccuper de tous les détails d'implémentation. A savoir que un rectangle c'est une hauteur et une largeur, il a dû définir comment se fait concrètement le calcul de surface. Donc ceci constitue la partie implémentation.
  7. 7. C'est un niveau interne qui n'est pas forcément utile à celui qui utilise le rectangle. Donc en programmation orientée objet, nous aurons non seulement la possibilité de regrouper en une seule et même entité des données et des traitements mais on va pouvoir également définir des niveaux de visibilité. Celui qui programme le nouveau type rectangle, concrètement une classe rectangle, va pouvoir dire ceci est un détail d'implémentation qui ne sera pas accessible à l'utilisateur externe. Ceci est une fonctionnalité que l'on souhaite offrir à l'utilisateur externe et donc qui va être accessible à cet utilisateur. Tout ce qui est accessible à l'utilisateur donc visible constitue ce que l'on appelle l'interface d'utilisation de la classe du type en question. Donc ici, dans notre classe rectangle, dans notre nouveau type rectangle, nous avons défini comme interface d'utilisation le calcul de surface. Le reste constitue des détails d'implémentation qui ne sont pas accessibles aux programmeurs qui utilisent le type rectangle. Et nous avons ici une clé fondamentale nous permettant d'atteindre l'objectif d'une meilleure robustesse de nos programmes face au changement. Typiquement, lorsque vous changez de voiture, même si la technologie du moteur a changé, l'interface, globalement, reste la même. Vous pouvez continuer, vous savez toujours conduire votre voiture même si les détails internes de mise en oeuvre de votre voiture ont changé entre-temps. Donc vous ne voyez de votre voiture que quelque chose d'abstrait. Vous ne voyez de votre voiture concrètement que ce qui vous permet de la conduire, à savoir le volant, l'accélérateur, la pédale de frein. Pour résumer, encapsuler c'est regrouper en une seule et même entité les données et le traitements qui la caractérisent, c'est aussi dissimuler les détails d'implémentation. L'interface d'utilisation que l'on définit en utilisant justement cet outillage de l'encapsulation. Et ce qui me permet d'aboutir à une abstraction donc une visions abstraite des
  8. 8. objets que en tant qu'utilisateur externe, je ne vois plus que en tant qu'objets manipulables au travers de leur interface d'utilisation. Donc concrètement, le programmeur concepteur va donc décider de l'existence d'un nouveau type et va devoir se préoccuper de tous les détails d'implémentation. Il va devoir décider de ce qui est visible pour le monde extérieur, de ce qui est utilisable et de ce qui ne l'est pas. Le programmeur utilisateur, de son côté, est client du nouveau type de données. Il va pouvoir l'utiliser. Mais va pouvoir l'utiliser uniquement au travers de l'interface, c'est-à -dire des méthodes visibles typiquement et n'aura pas accès aux détails internes. L'interface d'utilisation est typiquement ce qui va permettre d'établir le lien entre le concepteur développeur et l'utilisateur. Et de façon très concrète, cette interface va pouvoir être entièrement décrite par l'entête des méthodes qui sont offertes au programmeur utilisateur. Alors, un des intérêts fondamentaux de l'orienté objet est d'assurer une meilleure visibilité, une meilleure cohérence au programme. Vous avez ici sous les yeux deux programmes qui font sensiblement la même chose, qui calculent la surface d'un rectangle de largeur trois et de hauteur quatre. Nous anticiperons un tout petit peu sur la suite des séquences à venir, à savoir que l'on peut initialiser la largeur et la hauteur d'un rectangle selon cette syntaxe-là . Mais c'est surtout pour vous donner un aperçu de ce que donnerait au final le programme en terme de lisibilité. Donc si l'on compare les deux approches, eh bien on se rend compte qu'ici nous sommes en train de travailler avec des données de très bas niveau. Ici nous travaillons avec un rectangle, ce qui est beaucoup plus informatif quant aux intentions de programmation. En lisant ce programme, on sait tout de suite que l'on est en train de travailler avec
  9. 9. un rectangle. Ici le lien entre les données et les traitements ne se fait que par le biais du passage des arguments ce qui est indirect. Alors qu'ici le lien peut se faire de façon explicite. On appelle un calcul de surface sur un rectangle donné. De plus, de par le fait qu'en orienté objet on ne peut manipuler l'objet qu'au travers des méthodes des fonctionnalités de l'interface d'utilisation, cela permet de donner un cadre d'utilisation qui est beaucoup plus rigoureux. Par exemple ici, comme montré tout à l'heure, rien ne m'oblige dans cette approche à avoir des valeurs cohérentes ici pour la largeur et la hauteur. Donc la largeur et la hauteur qui appartiendraient à un même rectangle. Ici, cette erreur n'est plus possible puisque on manipule un rectangle particulier et donc forcément les valeurs qui y sont liées seront cohérentes. De plus, de par le même fait que l'utilisateur est contraint de passer par l'interface d'utilisation pour manipuler l'objet, il n'est pas impacté par des modifications d'implémentation interne. Donc comme évoqué précédemment si on décide plutôt, au lieu de modéliser un rectangle comme étant un objet de T, de deux attributs de type double, hauteur et largeur. On passe plutôt à une représentation sous la forme d'un tableau à deux entrées qui seraient les dimensions. Alors, si le programmeur concepteur de la classe rectangle a bien fait son travail et donc a adapté en conséquence le calcul de surface, celui qui utilise le calcul de surface n'est pas impacté. Voilà donc nous venons de voir sur ce petit exemple l'intérêt qui découle de séparer le niveau interne du niveau externe. On obtient donc un cadre d'utilisation plus rigoureux et les modifications de la structure interne restent invisibles à l'extérieur. Donc une des règles fondamentales qu'on a déjà vue dans l'introduction.
  10. 10. Les attributs, de par le fait qu'il faut faire des choix quant à leur modélisation, des choix techniques, des choix d'implémentation sont considérés comme des détails d'implémentation de façon systématique dans tout bon programme orienté objet. Pour résumer, lorsque l'on définit un nouveau type d'objet au travers d'une classe, on va être amené à définir les attributs caractéristiques de la classe ainsi que les méthodes qui lui sont spécifiques et on va devoir se préoccuper de définir concrètement ce qui est visible, l'interface d'utilisation, et ce qui ne l'est pas, les détails d'implémentation. Donc une fois que on aura décidé de ce qui est à cacher, on va aboutir à une représentation de l'objet pour l'utilisateur externe qui se résume à l'interface d'utilisation. Donc l'utilisateur externe n'aura de vision de cet objet qu'une vision abstraite qui est matérialisée par l'interface d'utilisation. Je ne vois d'un rectangle que son calcul de surface. Et si je veux suivre les bonnes règles de programmation orientée objet, je vais considérer que les attributs sont également des détails d'implémentation et donc l'interface va se limiter à un certain nombre de méthodes bien choisies. L'utilisateur externe n'aura de vision de l'objet que cette interface d'utilisation. À retenir de la séquence d'aujourd'hui le résultat du processus d'abstraction et ce que l'on appelle une classe qui me permet de désigner une catégorie d'objets. Une classe va définir dans un programme un nouveau type. Je dispose désormais du type rectangle que je peux manipuler dans un programme. Je peux déclarer des variables de ce type-là . Une réalisation concrète donc la déclaration d'une variable de ce nouveau type est ce qu'on appelle dans le jargon orienté objet, un objet. Et elle est généralement manipulée au travers d'une variable. À noter que l'on utilise couramment le terme d'instance pour désigner un objet. Pour résumer et pour illustrer le propos, celui qui écrit la classe rectangle va décider de l'existence conceptuelle de
  11. 11. ce nouveau type puis va le faire évidemment en écrivant un programme qui contient le code de cette classe rectangle. Celui qui l'utilise va utiliser ce nouveau type en déclarant des variables du type rectangle qui vont avoir une existence concrète au moment où le programme s'exécute donc au moment où on crée de nouveaux objets de ce type-là , on va pouvoir commencer à travailler avec ces objets concrètement dans un programme. Donc l'utilisateur va travailler concrètement avec des réalisations des objets de la classe rectangle. Nous voici arrivés au terme de la présentation de ces concepts centraux de l'orienté objet que sont l'encapsulation et l'abstraction. Vous allez, dès les séquences suivantes, commencer à les pratiquer très concrètement en C++.

×