{"id":116,"date":"2021-06-25T19:13:31","date_gmt":"2021-06-25T19:13:31","guid":{"rendered":"https:\/\/www.louismarchand.me\/?p=116"},"modified":"2021-06-30T15:20:38","modified_gmt":"2021-06-30T15:20:38","slug":"pourquoi-je-naime-pas-la-portee-privee","status":"publish","type":"post","link":"https:\/\/www.louismarchand.me\/index.php\/2021\/06\/25\/pourquoi-je-naime-pas-la-portee-privee\/","title":{"rendered":"Pourquoi je n&rsquo;aime pas la port\u00e9e priv\u00e9e"},"content":{"rendered":"<h2>\u00c0 quoi sert la port\u00e9e priv\u00e9e<\/h2>\n<p>Toute personne ayant d\u00e9velopp\u00e9 dans un langage de programmation orient\u00e9 objet bas\u00e9 sur le C++ (Java, C#, etc.) conna\u00eet la port\u00e9e priv\u00e9e. Cette port\u00e9e d&rsquo;attribut ou de m\u00e9thode permet de s&rsquo;assurer qu&rsquo;aucune autre classe n&rsquo;aura acc\u00e8s \u00e0 l&rsquo;attribut ou \u00e0 la m\u00e9thode en question. Cette port\u00e9e sert principalement \u00e0 prot\u00e9ger l&rsquo;int\u00e9grit\u00e9 des valeurs d&rsquo;un objet. Par exemple, si j&rsquo;ai la classe Java suivante dans laquelle je mets l&rsquo;enti\u00e8ret\u00e9 de mes attributs publics:<\/p>\n<div class=\"highlight\">\n<pre><span class=\"kd\">public<\/span> <span class=\"kd\">class<\/span> <span class=\"nc\">Personne<\/span> <span class=\"o\">{<\/span>\r\n\r\n    <span class=\"kd\">public<\/span> <span class=\"n\">String<\/span> <span class=\"n\">nom<\/span><span class=\"o\">;<\/span>\r\n\r\n    <span class=\"kd\">public<\/span> <span class=\"kt\">int<\/span> <span class=\"n\">age<\/span><span class=\"o\">;<\/span>\r\n\r\n<span class=\"o\">}<\/span>\r\n<\/pre>\n<\/div>\n<p>Le client de ma classe peut donc assigner n&rsquo;importe quelles valeurs aux attributs de ma classe. Par exemple, ce code Java serait valide:<\/p>\n<div class=\"highlight\">\n<pre><span class=\"n\">Personne<\/span> <span class=\"n\">lPersonne<\/span> <span class=\"o\">=<\/span> <span class=\"k\">new<\/span> <span class=\"n\">Personne<\/span><span class=\"o\">();<\/span>\r\n<span class=\"n\">lPersonne<\/span><span class=\"o\">.<\/span><span class=\"na\">nom<\/span> <span class=\"o\">=<\/span> <span class=\"s\">\"\"<\/span><span class=\"o\">;<\/span>\r\n<span class=\"n\">lPersonne<\/span><span class=\"o\">.<\/span><span class=\"na\">age<\/span> <span class=\"o\">=<\/span> <span class=\"o\">-<\/span><span class=\"mi\">8<\/span><span class=\"o\">;<\/span>\r\n<\/pre>\n<\/div>\n<p>Le probl\u00e8me ici, c&rsquo;est que malgr\u00e9 que le code est valide, les valeurs entr\u00e9es ne font aucun sens. En effet, une personne ne peut pas avoir aucun nom et un age n\u00e9gatif. C&rsquo;est la raison pour laquelle nous pouvons utiliser des accesseurs et des assignateurs (\u00ab\u00a0getter\u00a0\u00bb et \u00ab\u00a0setter\u00a0\u00bb). Je pourrais donc mettre mes attributs priv\u00e9s, les rendres accessibles par des accesseurs et valider les valeurs par des assignateurs. Voici l&rsquo;exemple Java modifi\u00e9:<\/p>\n<div class=\"highlight\">\n<pre><span class=\"kd\">public<\/span> <span class=\"kd\">class<\/span> <span class=\"nc\">Personne<\/span> <span class=\"o\">{<\/span>\r\n\r\n    <span class=\"kd\">private<\/span> <span class=\"n\">String<\/span> <span class=\"n\">nom<\/span><span class=\"o\">;<\/span>\r\n\r\n    <span class=\"kd\">public<\/span> <span class=\"n\">String<\/span> <span class=\"nf\">getNom<\/span><span class=\"o\">()<\/span> <span class=\"o\">{<\/span>\r\n        <span class=\"k\">return<\/span> <span class=\"n\">nom<\/span><span class=\"o\">;<\/span>\r\n    <span class=\"o\">}<\/span>\r\n\r\n    <span class=\"kd\">public<\/span> <span class=\"kt\">void<\/span> <span class=\"nf\">setNom<\/span><span class=\"o\">(<\/span><span class=\"n\">String<\/span> <span class=\"n\">aNom<\/span><span class=\"o\">)<\/span> <span class=\"o\">{<\/span>\r\n        <span class=\"k\">if<\/span> <span class=\"o\">(<\/span><span class=\"n\">aNom<\/span> <span class=\"o\">!=<\/span> <span class=\"kc\">null<\/span> <span class=\"o\">&amp;&amp;<\/span> <span class=\"o\">!<\/span> <span class=\"n\">aNom<\/span><span class=\"o\">.<\/span><span class=\"na\">isEmpty<\/span><span class=\"o\">()){<\/span>\r\n            <span class=\"n\">nom<\/span> <span class=\"o\">=<\/span> <span class=\"n\">aNom<\/span><span class=\"o\">;<\/span>\r\n        <span class=\"o\">}<\/span> <span class=\"k\">else<\/span> <span class=\"o\">{<\/span>\r\n            <span class=\"k\">throw<\/span> <span class=\"k\">new<\/span> <span class=\"n\">IllegalArgumentException<\/span><span class=\"o\">(<\/span><span class=\"s\">\"Le nom n'est pas valide.\"<\/span><span class=\"o\">);<\/span>\r\n        <span class=\"o\">}<\/span>\r\n    <span class=\"o\">}<\/span>\r\n\r\n    <span class=\"kd\">private<\/span> <span class=\"kt\">int<\/span> <span class=\"n\">age<\/span><span class=\"o\">;<\/span>\r\n\r\n    <span class=\"kd\">public<\/span> <span class=\"kt\">int<\/span> <span class=\"nf\">getAge<\/span><span class=\"o\">()<\/span> <span class=\"o\">{<\/span>\r\n        <span class=\"k\">return<\/span> <span class=\"n\">age<\/span><span class=\"o\">;<\/span>\r\n    <span class=\"o\">}<\/span>\r\n\r\n    <span class=\"kd\">public<\/span> <span class=\"kt\">void<\/span> <span class=\"nf\">setAge<\/span><span class=\"o\">(<\/span><span class=\"kt\">int<\/span> <span class=\"n\">aAge<\/span><span class=\"o\">)<\/span> <span class=\"o\">{<\/span>\r\n        <span class=\"k\">if<\/span> <span class=\"o\">(<\/span><span class=\"n\">aAge<\/span> <span class=\"o\">&gt;=<\/span> <span class=\"mi\">0<\/span><span class=\"o\">){<\/span>\r\n            <span class=\"n\">age<\/span> <span class=\"o\">=<\/span> <span class=\"n\">aAge<\/span><span class=\"o\">;<\/span>\r\n        <span class=\"o\">}<\/span> <span class=\"k\">else<\/span> <span class=\"o\">{<\/span>\r\n            <span class=\"k\">throw<\/span> <span class=\"k\">new<\/span> <span class=\"n\">IllegalArgumentException<\/span><span class=\"o\">(<\/span><span class=\"s\">\"L'age n'est pas valide.\"<\/span><span class=\"o\">);<\/span>\r\n        <span class=\"o\">}<\/span>\r\n    <span class=\"o\">}<\/span>\r\n\r\n<span class=\"o\">}<\/span>\r\n<\/pre>\n<\/div>\n<p>On voit maintenant que le client de la classe ne peut plus acc\u00e9der directement aux attributs puisque ces derniers sont priv\u00e9s. Le client doit maintenant utiliser les assignateurs (\u00ab\u00a0setNom\u00a0\u00bb et \u00ab\u00a0setAge\u00a0\u00bb) pour assigner des valeurs aux attributs. De plus ces assignateurs ont un m\u00e9canisme d&rsquo;exceptions leur permettant de v\u00e9rifier que les valeurs sont correctes avant d&rsquo;effectuer l&rsquo;assignation de l&rsquo;attribut.<\/p>\n<h2>Le priv\u00e9 dans le contexte d&rsquo;h\u00e9ritage<\/h2>\n<p>Les clients de la classe ne sont pas les seules entit\u00e9s pouvant assigner de mauvaises valeurs dans les attributs de l&rsquo;objet. Cette probl\u00e9matique s&rsquo;applique \u00e9galement aux descendants de la classe. Par exemple, si je faisais la class Bebe qui repr\u00e9sente une Personne d&rsquo;age entre 0 et 1. Il est possible dans ce cas que les parents n&rsquo;aient pas encore trouv\u00e9 de nom pour ce b\u00e9b\u00e9. Je pourrais avoir le code Java suivant:<\/p>\n<div class=\"highlight\">\n<pre><span class=\"kd\">public<\/span> <span class=\"kd\">class<\/span> <span class=\"nc\">Bebe<\/span> <span class=\"kd\">extends<\/span> <span class=\"n\">Personne<\/span> <span class=\"o\">{<\/span>\r\n\r\n    <span class=\"nd\">@Override<\/span>\t\r\n    <span class=\"kd\">public<\/span> <span class=\"kt\">void<\/span> <span class=\"nf\">setNom<\/span><span class=\"o\">(<\/span><span class=\"n\">String<\/span> <span class=\"n\">aNom<\/span><span class=\"o\">)<\/span> <span class=\"o\">{<\/span>\r\n        <span class=\"k\">if<\/span> <span class=\"o\">(<\/span><span class=\"n\">aNom<\/span> <span class=\"o\">!=<\/span> <span class=\"kc\">null<\/span><span class=\"o\">){<\/span>\r\n            <span class=\"n\">nom<\/span> <span class=\"o\">=<\/span> <span class=\"n\">aNom<\/span><span class=\"o\">;<\/span>\r\n        <span class=\"o\">}<\/span> <span class=\"k\">else<\/span> <span class=\"o\">{<\/span>\r\n            <span class=\"k\">throw<\/span> <span class=\"k\">new<\/span> <span class=\"n\">IllegalArgumentException<\/span><span class=\"o\">(<\/span><span class=\"s\">\"Le nom n'est pas valide.\"<\/span><span class=\"o\">);<\/span>\r\n        <span class=\"o\">}<\/span>\r\n    <span class=\"o\">}<\/span>\r\n\r\n    <span class=\"kd\">public<\/span> <span class=\"kt\">void<\/span> <span class=\"nf\">setAge<\/span><span class=\"o\">(<\/span><span class=\"kt\">int<\/span> <span class=\"n\">aAge<\/span><span class=\"o\">)<\/span> <span class=\"o\">{<\/span>\r\n        <span class=\"k\">if<\/span> <span class=\"o\">(<\/span><span class=\"n\">aAge<\/span> <span class=\"o\">&gt;=<\/span> <span class=\"mi\">0<\/span> <span class=\"o\">&amp;&amp;<\/span> <span class=\"n\">aAge<\/span> <span class=\"o\">&lt;=<\/span> <span class=\"mi\">1<\/span><span class=\"o\">){<\/span>\r\n            <span class=\"n\">age<\/span> <span class=\"o\">=<\/span> <span class=\"n\">aAge<\/span><span class=\"o\">;<\/span>\r\n        <span class=\"o\">}<\/span> <span class=\"k\">else<\/span> <span class=\"o\">{<\/span>\r\n            <span class=\"k\">throw<\/span> <span class=\"k\">new<\/span> <span class=\"n\">IllegalArgumentException<\/span><span class=\"o\">(<\/span><span class=\"s\">\"L'age n'est pas valide.\"<\/span><span class=\"o\">);<\/span>\r\n        <span class=\"o\">}<\/span>\r\n    <span class=\"o\">}<\/span>\r\n\r\n<span class=\"o\">}<\/span>\r\n<\/pre>\n<\/div>\n<p>Il est important de voir que ce code ne compilera pas puisque les attributs nom et age sont priv\u00e9s et ne peuvent donc pas \u00eatre assign\u00e9. On peut utiliser les assignateurs de la classe Personne pour faire le travail. Dans ce cas, j&rsquo;aurais le code Java:<\/p>\n<div class=\"highlight\">\n<pre><span class=\"kd\">public<\/span> <span class=\"kd\">class<\/span> <span class=\"nc\">Bebe<\/span> <span class=\"kd\">extends<\/span> <span class=\"n\">Personne<\/span> <span class=\"o\">{<\/span>\r\n\r\n    <span class=\"nd\">@Override<\/span>\t\r\n    <span class=\"kd\">public<\/span> <span class=\"kt\">void<\/span> <span class=\"nf\">setNom<\/span><span class=\"o\">(<\/span><span class=\"n\">String<\/span> <span class=\"n\">aNom<\/span><span class=\"o\">)<\/span> <span class=\"o\">{<\/span>\r\n        <span class=\"k\">if<\/span> <span class=\"o\">(<\/span><span class=\"n\">aNom<\/span> <span class=\"o\">!=<\/span> <span class=\"kc\">null<\/span><span class=\"o\">){<\/span>\r\n            <span class=\"kd\">super<\/span><span class=\"o\">.<\/span><span class=\"na\">setNom<\/span><span class=\"o\">(<\/span><span class=\"n\">aNom<\/span><span class=\"o\">);<\/span>\r\n        <span class=\"o\">}<\/span> <span class=\"k\">else<\/span> <span class=\"o\">{<\/span>\r\n            <span class=\"k\">throw<\/span> <span class=\"k\">new<\/span> <span class=\"n\">IllegalArgumentException<\/span><span class=\"o\">(<\/span><span class=\"s\">\"Le nom n'est pas valide.\"<\/span><span class=\"o\">);<\/span>\r\n        <span class=\"o\">}<\/span>\r\n    <span class=\"o\">}<\/span>\r\n\r\n    <span class=\"nd\">@Override<\/span>\t\r\n    <span class=\"kd\">public<\/span> <span class=\"kt\">void<\/span> <span class=\"nf\">setAge<\/span><span class=\"o\">(<\/span><span class=\"kt\">int<\/span> <span class=\"n\">aAge<\/span><span class=\"o\">)<\/span> <span class=\"o\">{<\/span>\r\n        <span class=\"k\">if<\/span> <span class=\"o\">(<\/span><span class=\"n\">aAge<\/span> <span class=\"o\">&gt;=<\/span> <span class=\"mi\">0<\/span> <span class=\"o\">&amp;&amp;<\/span> <span class=\"n\">aAge<\/span> <span class=\"o\">&lt;=<\/span> <span class=\"mi\">1<\/span><span class=\"o\">){<\/span>\r\n            <span class=\"kd\">super<\/span><span class=\"o\">.<\/span><span class=\"na\">setAge<\/span><span class=\"o\">(<\/span><span class=\"n\">aAge<\/span><span class=\"o\">);<\/span>\r\n        <span class=\"o\">}<\/span> <span class=\"k\">else<\/span> <span class=\"o\">{<\/span>\r\n            <span class=\"k\">throw<\/span> <span class=\"k\">new<\/span> <span class=\"n\">IllegalArgumentException<\/span><span class=\"o\">(<\/span><span class=\"s\">\"L'age n'est pas valide.\"<\/span><span class=\"o\">);<\/span>\r\n        <span class=\"o\">}<\/span>\r\n    <span class=\"o\">}<\/span>\r\n\r\n<span class=\"o\">}<\/span>\r\n<\/pre>\n<\/div>\n<p>Dans ce cas, le \u00ab\u00a0setAge\u00a0\u00bb fonctionnera sans probl\u00e8me puisque la particularit\u00e9 de Bebe (age entre 0 et 1) est conforme \u00e0 la condition de personne (age plus grand ou \u00e9gal \u00e0 0). Par contre, le \u00ab\u00a0setNom\u00a0\u00bb ne fonctionnera pas puisque le \u00ab\u00a0setNom\u00a0\u00bb de Bebe accepte les cha\u00eenes vide, mais le \u00ab\u00a0setNom\u00a0\u00bb de Personne les refuses.<\/p>\n<h2>Le probl\u00e8me<\/h2>\n<p>Maintenant que nous avons bien pr\u00e9cis\u00e9 \u00e0 quoi sert la port\u00e9e priv\u00e9e, je peux pr\u00e9senter le probl\u00e8me. Je veux pr\u00e9ciser que tous les cas pr\u00e9sent\u00e9s plus haut sont tout \u00e0 fait corrects et permettre de montrer que la port\u00e9e priv\u00e9e permet de bien valider les valeurs assign\u00e9es aux attributs de la classe.<\/p>\n<p>Le probl\u00e8me est au niveau id\u00e9ologique, mais peut avoir des r\u00e9percussions au niveau fonctionnel.<\/p>\n<p>Au niveau id\u00e9ologique, c&rsquo;est que la port\u00e9e priv\u00e9e ne respecte pas le principe de programmation orient\u00e9e objet. En effet, l&rsquo;h\u00e9ritage dans le principe de programmation orient\u00e9e objet est un lien de sp\u00e9cialisation\/g\u00e9n\u00e9ralisation (l&rsquo;enfant sp\u00e9cialise et le parent g\u00e9n\u00e9ralise). Par exemple, une Pomme est une version sp\u00e9cialis\u00e9e d&rsquo;un Fruit, qui lui est plus g\u00e9n\u00e9ral. En d&rsquo;autres mots, l&rsquo;enfant repr\u00e9sente une sous-cat\u00e9gorie du parent, avec des particularit\u00e9s suppl\u00e9mentaires. Donc, une Pomme est un Fruit, avec des particularit\u00e9s suppl\u00e9mentaires (forme, couleur, go\u00fbt, etc.).<\/p>\n<p>Le probl\u00e8me repose ici. L&rsquo;enfant ne doit pas \u00eatre consid\u00e9r\u00e9 comme quelque chose de distinct du parent. L&rsquo;enfant compl\u00e8te le parent. Il s&rsquo;agit du m\u00eame objet vu d&rsquo;un angle diff\u00e9rent (plus g\u00e9n\u00e9ral ou plus sp\u00e9cifique). Il est donc compl\u00e8tement illogique qu&rsquo;il existe des choses (au sens large) que le parent peut faire, mais que l&rsquo;enfant ne peut pas faire (l&rsquo;inverse n&rsquo;est pas vrai puisque l&rsquo;enfant sp\u00e9cialise le parent). En d&rsquo;autres mots, puisque la Pomme est un Fruit, la Pomme devrait avoir acc\u00e8s \u00e0 tout ce que le Fruit a acc\u00e8s.<\/p>\n<p>Puisque la port\u00e9e priv\u00e9e permet de rendre accessible certains attributs et m\u00e9thodes au parent qui n&rsquo;est pas accessible aux enfants et que dans le principe de programmation orient\u00e9e objet, l&rsquo;enfant devrait avoir acc\u00e8s \u00e0 tout ce que le parent a acc\u00e8s, on en d\u00e9duit que la port\u00e9e priv\u00e9e n&rsquo;est pas conforme au principe de programmation orient\u00e9e objet.<\/p>\n<p>Cette probl\u00e9matique peut \u00e9galement avoir un effet au niveau fonctionnel. En effet, il arrive souvent qu&rsquo;on cr\u00e9e des attributs en lecture seul dans une classe. Afin de faire ce type d&rsquo;attribut, on utilise un attribut priv\u00e9 qui ne contient qu&rsquo;un accesseur ou \u00ab\u00a0getter\u00a0\u00bb (pas d&rsquo;assignateur ou \u00ab\u00a0setter\u00a0\u00bb). Ce faisant, les classes descendantes se retrouvent \u00e0 ne plus avoir de contr\u00f4le sur un de leurs propres attributs. Il est bien entendu possible de mettre un assignateur prot\u00e9g\u00e9, mais il arrive souvent que la classe que nous souhaitons h\u00e9riter n&rsquo;est pas une classe que nous pouvons modifier facilement (par exemple, classes de librairie) et il est donc compl\u00e8tement impossible d&rsquo;y ajouter des assignateurs prot\u00e9g\u00e9s.<\/p>\n<h2>\u00c0 propos de la port\u00e9e prot\u00e9g\u00e9e<\/h2>\n<p>La port\u00e9e prot\u00e9g\u00e9e r\u00e8gle en effet le probl\u00e8me de non-conformit\u00e9 au principe de programmation orient\u00e9e objet. En mettant toutes nos attributs et m\u00e9thodes d&rsquo;impl\u00e9mentation en port\u00e9e prot\u00e9g\u00e9e, nous nous assurons que les descendants de la classe ont acc\u00e8s \u00e0 l&rsquo;enti\u00e8ret\u00e9 de leurs m\u00e9thodes et attributs.<\/p>\n<p>Par contre, un autre probl\u00e8me survient, en mettant tous en port\u00e9e prot\u00e9g\u00e9e, on se retrouve avec une classe qui ne peut plus prot\u00e9ger l&rsquo;int\u00e9grit\u00e9 de ces valeurs. La seule solution consiste en fait en s&rsquo;assurant de mettre tous les attributs priv\u00e9s et de mettre toutes les m\u00e9thodes (incluant les accesseurs et les assignateurs) soit prot\u00e9g\u00e9s ou publics. De plus, il faut s&rsquo;assurer de toujours mettre des assignateurs et des accesseurs \u00e0 tous les attributs, peu importe que ce soit des attributs en lecture ou en \u00e9criture seulement, ou bien des attributs\/variables d&rsquo;impl\u00e9mentation de la classe. De cette mani\u00e8re, malgr\u00e9 que le code ne respecte toujours pas le principe de programmation orient\u00e9e objet (puisque les attributs ne sont pas directement accessibles par les descendants de la classe), on se retrouve tout de m\u00eame avec quelque chose de relativement fiable.<\/p>\n<h2>Quels sont les alternatives?<\/h2>\n<p>Lors de l&rsquo;\u00e9criture de son livre \u00ab\u00a0Object-Oriented Software Construction\u00a0\u00bb, un des livres les plus influant du domaine de la programmation orient\u00e9e objet, le chercher Bertrand Meyer a trouv\u00e9 une solution tr\u00e8s \u00e9l\u00e9gante \u00e0 ce probl\u00e8me: les invariants de classe.<\/p>\n<p>L&rsquo;id\u00e9e d&rsquo;un invariant de classe, c&rsquo;est d&rsquo;\u00e9tablir dans la classe (ainsi que dans les classes descendantes), une liste de r\u00e8gles qui doivent toujours \u00eatre respect\u00e9es dans les objets qui instancient cette classe. En d&rsquo;autres mots, il n&rsquo;est pas de la responsabilit\u00e9 des assignateurs de la classe de valider les valeurs de la classe, mais bien \u00e0 la classe elle-m\u00eame. Puisque les invariants sont h\u00e9rit\u00e9s et document\u00e9s, tous les anc\u00eatres de la classe h\u00e9ritent de ces invariants et ont l&rsquo;obligation de les respecter. Lorsqu&rsquo;une m\u00e9thode se termine, tous les invariants sont valid\u00e9s et si un de ces invariants n&rsquo;est pas valide, une exception est lanc\u00e9e.<\/p>\n<p>Voici un exemple d&rsquo;invariant fait dans le langage Java en utilisant une librairie de contrat (Java ne g\u00e8re pas les contrats par d\u00e9faut):<\/p>\n<div class=\"highlight\">\n<pre><span class=\"nd\">@Contract<\/span><span class=\"o\">(<\/span>\r\n           <span class=\"n\">nom<\/span> <span class=\"o\">!=<\/span> <span class=\"kc\">null<\/span> <span class=\"o\">&amp;&amp;<\/span>\r\n           <span class=\"o\">!<\/span><span class=\"n\">nom<\/span><span class=\"o\">.<\/span><span class=\"na\">isEmpty<\/span><span class=\"o\">()<\/span> <span class=\"o\">&amp;&amp;<\/span>\r\n           <span class=\"n\">age<\/span> <span class=\"o\">&gt;=<\/span> <span class=\"mi\">0<\/span><span class=\"o\">)<\/span>\r\n<span class=\"kd\">public<\/span> <span class=\"kd\">class<\/span> <span class=\"nc\">Personne<\/span> <span class=\"o\">{<\/span>\r\n\r\n    <span class=\"kd\">protected<\/span> <span class=\"n\">String<\/span> <span class=\"n\">nom<\/span><span class=\"o\">;<\/span>\r\n\r\n    <span class=\"kd\">public<\/span> <span class=\"n\">String<\/span> <span class=\"nf\">getNom<\/span><span class=\"o\">()<\/span> <span class=\"o\">{<\/span>\r\n        <span class=\"k\">return<\/span> <span class=\"n\">nom<\/span><span class=\"o\">;<\/span>\r\n    <span class=\"o\">}<\/span>\r\n\r\n    <span class=\"kd\">public<\/span> <span class=\"kt\">void<\/span> <span class=\"nf\">setNom<\/span><span class=\"o\">(<\/span><span class=\"n\">String<\/span> <span class=\"n\">aNom<\/span><span class=\"o\">)<\/span> <span class=\"o\">{<\/span>\r\n        <span class=\"k\">if<\/span> <span class=\"o\">(<\/span><span class=\"n\">aNom<\/span> <span class=\"o\">!=<\/span> <span class=\"kc\">null<\/span> <span class=\"o\">&amp;&amp;<\/span> <span class=\"o\">!<\/span> <span class=\"n\">aNom<\/span><span class=\"o\">.<\/span><span class=\"na\">isEmpty<\/span><span class=\"o\">()){<\/span>\r\n            <span class=\"n\">nom<\/span> <span class=\"o\">=<\/span> <span class=\"n\">aNom<\/span><span class=\"o\">;<\/span>\r\n        <span class=\"o\">}<\/span> <span class=\"k\">else<\/span> <span class=\"o\">{<\/span>\r\n            <span class=\"k\">throw<\/span> <span class=\"k\">new<\/span> <span class=\"n\">IllegalArgumentException<\/span><span class=\"o\">(<\/span><span class=\"s\">\"Le nom n'est pas valide.\"<\/span><span class=\"o\">);<\/span>\r\n        <span class=\"o\">}<\/span>\r\n    <span class=\"o\">}<\/span>\r\n\r\n    <span class=\"kd\">protected<\/span> <span class=\"kt\">int<\/span> <span class=\"n\">age<\/span><span class=\"o\">;<\/span>\r\n\r\n    <span class=\"kd\">public<\/span> <span class=\"kt\">int<\/span> <span class=\"nf\">getAge<\/span><span class=\"o\">()<\/span> <span class=\"o\">{<\/span>\r\n        <span class=\"k\">return<\/span> <span class=\"n\">age<\/span><span class=\"o\">;<\/span>\r\n    <span class=\"o\">}<\/span>\r\n\r\n    <span class=\"kd\">public<\/span> <span class=\"kt\">void<\/span> <span class=\"nf\">setAge<\/span><span class=\"o\">(<\/span><span class=\"kt\">int<\/span> <span class=\"n\">aAge<\/span><span class=\"o\">)<\/span> <span class=\"o\">{<\/span>\r\n        <span class=\"k\">if<\/span> <span class=\"o\">(<\/span><span class=\"n\">aAge<\/span> <span class=\"o\">&gt;=<\/span> <span class=\"mi\">0<\/span><span class=\"o\">){<\/span>\r\n            <span class=\"n\">age<\/span> <span class=\"o\">=<\/span> <span class=\"n\">aAge<\/span><span class=\"o\">;<\/span>\r\n        <span class=\"o\">}<\/span> <span class=\"k\">else<\/span> <span class=\"o\">{<\/span>\r\n            <span class=\"k\">throw<\/span> <span class=\"k\">new<\/span> <span class=\"n\">IllegalArgumentException<\/span><span class=\"o\">(<\/span><span class=\"s\">\"L'age n'est pas valide.\"<\/span><span class=\"o\">);<\/span>\r\n        <span class=\"o\">}<\/span>\r\n    <span class=\"o\">}<\/span>\r\n\r\n<span class=\"o\">}<\/span>\r\n<\/pre>\n<\/div>\n<p>Cette technique a l&rsquo;avantage de prot\u00e9ger enti\u00e8rement les attributs de la classe, et ce, m\u00eame si les attributs sont directement assignables par les descendants de la classe. De plus, cette m\u00e9thode respecte enti\u00e8rement le principe objet puisque l&rsquo;invariant s&rsquo;applique autant \u00e0 la classe Personne qu&rsquo;\u00e0 ses descendants. En d&rsquo;autres mots, contrairement au mot cl\u00e9 priv\u00e9 qui enl\u00e8ve de l&rsquo;information aux descendants de la classe, l&rsquo;invariant qui permet la m\u00eame protection des donn\u00e9es, est une information qui est h\u00e9rit\u00e9e (demeure donc accessible) dans les descendants.<\/p>\n<h2>Petite parenth\u00e8se par rapport \u00e0 la port\u00e9e prot\u00e9g\u00e9e en Java<\/h2>\n<p>Les cr\u00e9ateurs de langage ont souvent une certaine obsession de s&rsquo;assurer de garder minimal le nombre de mots cl\u00e9s dans le langage. Il s&rsquo;agit en effet d&rsquo;un \u00e9l\u00e9ment int\u00e9ressant, car plus le langage est minimal, plus il sera facile de cr\u00e9er le compilateur ou l&rsquo;interpr\u00e9teur et plus il sera facile d&rsquo;apprendre le langage. Par contre, certains mauvais \u00ab\u00a0desing\u00a0\u00bb de langage peut appara\u00eetre suite \u00e0 cette pr\u00e9occupation.<\/p>\n<p>La port\u00e9e prot\u00e9g\u00e9e de Java est un excellent exemple de cela. Initialement, la port\u00e9e prot\u00e9g\u00e9e permettait de permettre \u00e0 la classe en cours ainsi qu&rsquo;\u00e0 ces descendants d&rsquo;acc\u00e9der \u00e0 des attributs ou des m\u00e9thodes de la classe. Comme nous l&rsquo;avons vu, cette port\u00e9e est tr\u00e8s int\u00e9ressante puisqu&rsquo;elle permet de respecter le principe de programmation orient\u00e9e objet.<\/p>\n<p>Par contre, il existe un autre type de port\u00e9, plus rare et dont l&rsquo;utilisation est plus subtile, mais qui peut, dans certains cas, \u00eatre tr\u00e8s int\u00e9ressant \u00e0 avoir dans un langage. Il s&rsquo;agit de la port\u00e9 ami. Cette port\u00e9e permet \u00e0 certaines autres classes du syst\u00e8me, en plus de la classe en cours et des descendants, d&rsquo;avoir acc\u00e8s aux attributs ou m\u00e9thodes. Il pourrait \u00eatre int\u00e9ressant par exemple pour la classe Tableau de g\u00e9rer une autre classe Cellule, mais sans que d&rsquo;autres clients puissent utiliser cette Cellule. Le Tableau serait donc consid\u00e9r\u00e9 comme un ami de Cellule et en tant qu&rsquo;ami, il aurait acc\u00e8s \u00e0 certains attributs et certaines m\u00e9thodes de Cellule qui ne sont pas publics.<\/p>\n<p>De mani\u00e8re \u00e0 pouvoir permettre ce type de port\u00e9e, mais en r\u00e9utilisant un type de port\u00e9e qui existait d\u00e9j\u00e0 dans le langage, Java a ajout\u00e9 comme r\u00e8gle \u00e0 sa port\u00e9e prot\u00e9g\u00e9e indiquant qu&rsquo;en plus de la classe en cours et de ses descendants, l&rsquo;attribut ou la m\u00e9thode prot\u00e9g\u00e9e serait accessible \u00e0 partir de toutes les classes du \u00ab\u00a0package\u00a0\u00bb en cours.<\/p>\n<p>Cette m\u00e9canique cause plusieurs probl\u00e8mes.<\/p>\n<p>Premi\u00e8rement, la port\u00e9e prot\u00e9g\u00e9e, qui je le rappelle est la seule mani\u00e8re en java d&rsquo;avoir un attribut ou une m\u00e9thode d&rsquo;impl\u00e9mentation dans une classe tout en respectant le principe de programmation orient\u00e9e objet, devient accessible par d&rsquo;autres classes, ce qui contrevient au principe de masquage d&rsquo;information de la programmation orient\u00e9e objet. Il en revient qu&rsquo;en Java, la seule mani\u00e8re de faire des classes qui respectent les principes de programmation orient\u00e9e objet (autre que des classes ne contenant que des m\u00e9thodes publiques), c&rsquo;est de faire une classe par \u00ab\u00a0Package\u00a0\u00bb, ce qui est loin d&rsquo;\u00eatre propre ou m\u00eame pratique.<\/p>\n<p>Ensuite, consid\u00e9rant la mani\u00e8re que la majorit\u00e9 des programmeurs \u00e9crivent du code, on voit qu&rsquo;il est tr\u00e8s rare qu&rsquo;il y a une grande quantit\u00e9 de \u00ab\u00a0package\u00a0\u00bb Java. On obtient donc que le fait de faire des attributs ou des m\u00e9thodes prot\u00e9g\u00e9es revient g\u00e9n\u00e9ralement \u00e0 faire des attributs ou des m\u00e9thodes publics (ou presque). Ce fait peut causer de grande confusion puisque le compilateur laissera passer des manipulations qui clairement auraient d\u00fb \u00eatre interdites.<\/p>\n<p>Enfin, cette probl\u00e9matique fait que plusieurs programmeurs (particuli\u00e8rement les programmeurs avec peu d&rsquo;exp\u00e9rience) comprennent mal la port\u00e9e prot\u00e9g\u00e9e, ne l&rsquo;utilise que tr\u00e8s peu, ou inversement l&rsquo;utilise toujours au lieu d&rsquo;utiliser la port\u00e9e publique.<\/p>\n<p>Il aurait donc \u00e9t\u00e9 plus acceptable de cr\u00e9er une m\u00e9canique de port\u00e9e diff\u00e9rente \u00e0 la port\u00e9e prot\u00e9g\u00e9e pour g\u00e9rer la port\u00e9e amie en Java.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>\u00c0 quoi sert la port\u00e9e priv\u00e9e Toute personne ayant d\u00e9velopp\u00e9 dans un langage de programmation orient\u00e9 objet bas\u00e9 sur le C++ (Java, C#, etc.) conna\u00eet la port\u00e9e priv\u00e9e. Cette port\u00e9e d&rsquo;attribut ou de m\u00e9thode permet de s&rsquo;assurer qu&rsquo;aucune autre classe n&rsquo;aura acc\u00e8s \u00e0 l&rsquo;attribut ou \u00e0 la m\u00e9thode en question. Cette port\u00e9e sert principalement \u00e0&hellip; <a class=\"more-link\" href=\"https:\/\/www.louismarchand.me\/index.php\/2021\/06\/25\/pourquoi-je-naime-pas-la-portee-privee\/\">Continue reading <span class=\"screen-reader-text\">Pourquoi je n&rsquo;aime pas la port\u00e9e priv\u00e9e<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[5,6],"tags":[7,8],"class_list":["post-116","post","type-post","status-publish","format-standard","hentry","category-programmation","category-programmation-orientee-objet-programmation","tag-programmation","tag-programmation-orientee-objet","entry"],"_links":{"self":[{"href":"https:\/\/www.louismarchand.me\/index.php\/wp-json\/wp\/v2\/posts\/116","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.louismarchand.me\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.louismarchand.me\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.louismarchand.me\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.louismarchand.me\/index.php\/wp-json\/wp\/v2\/comments?post=116"}],"version-history":[{"count":7,"href":"https:\/\/www.louismarchand.me\/index.php\/wp-json\/wp\/v2\/posts\/116\/revisions"}],"predecessor-version":[{"id":126,"href":"https:\/\/www.louismarchand.me\/index.php\/wp-json\/wp\/v2\/posts\/116\/revisions\/126"}],"wp:attachment":[{"href":"https:\/\/www.louismarchand.me\/index.php\/wp-json\/wp\/v2\/media?parent=116"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.louismarchand.me\/index.php\/wp-json\/wp\/v2\/categories?post=116"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.louismarchand.me\/index.php\/wp-json\/wp\/v2\/tags?post=116"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}