Derniers messages sur Zeste de Savoirhttps://zestedesavoir.com/forums/2019-06-12T14:08:02+02:00Les derniers messages parus sur le forum de Zeste de Savoir.Cette classe est-elle un sous type légitime ?, message #2044342019-06-12T14:08:02+02:00Ksass`Peuk/@Ksass%60Peukhttps://zestedesavoir.com/forums/sujet/12577/cette-classe-est-elle-un-sous-type-legitime/?page=2#p204434<figure><blockquote>
<p>Je me trompe où cette propriété temporelle est un invariant ponctuel? C’est à dire que tu exiges parfois, mais pas toujours?</p>
</blockquote><figcaption><a href="https://zestedesavoir.com/forums/sujet/12577/cette-classe-est-elle-un-sous-type-legitime/?page=2#p204429">lmghs</a></figcaption></figure>
<p>Au niveau de l’objet qui a une propriété temporelle, ce n’est pas tant une exigence qu’une conséquence de tes exigences et des actions que tu effectues sur l’objet. </p>
<p>Je ne sais pas si on peut parler d’invariant ponctuel. En particulier, si je me souviens bien (mais là pour le coup, je ne suis pas du tout expert sur la logique temporelle), il y a des propriétés que tu ne peux pas si facilement exprimer hors de la logique temporelle, notamment parce que ça fait intervenir des propriétés existentielles potentiellement assez méchantes qui parlent de ton chemin d’exécution.</p>Cette classe est-elle un sous type légitime ?, message #2044292019-06-12T13:15:17+02:00lmghs/@lmghshttps://zestedesavoir.com/forums/sujet/12577/cette-classe-est-elle-un-sous-type-legitime/?page=2#p204429<p>Je me trompe où cette propriété temporelle est un invariant ponctuel? C’est à dire que tu exiges parfois, mais pas toujours?</p>Cette classe est-elle un sous type légitime ?, message #2044252019-06-12T12:08:02+02:00Ksass`Peuk/@Ksass%60Peukhttps://zestedesavoir.com/forums/sujet/12577/cette-classe-est-elle-un-sous-type-legitime/?page=2#p204425<figure><blockquote>
<p>Le départ de la discussion c’était quand même de savoir quand il est souhaitable de considérer qu’un type est un sous-type viable, si tu arrives a une situation ou tu rejettes un sous-type tout en disant que le raisonnement ayant conduit au rejet n’est pas souhaitable, je trouve ça un peu paradoxale <img src="/static/smileys/smile.png" alt=":)" class="smiley"> .</p>
</blockquote><figcaption><a href="https://zestedesavoir.com/forums/sujet/12577/cette-classe-est-elle-un-sous-type-legitime/?page=2#p204423">Freedom</a></figcaption></figure>
<p>Bah elle est pas souhaitable mais malheureusement, on doit faire avec. Les propriétés temporelles c’est pénible à modéliser et en plus on a des types qui en usent pas mal (par exemple les types fichiers qui demandent à ce que le fichier soit ouvert avant de pouvoir lire, pour prendre un cas super trivial).</p>
<figure><blockquote>
<p>Lorsque cette situation arrive <sup id="fnref-1-OTMtraLxN"><a href="#fn-1-OTMtraLxN" class="footnote-ref">1</a></sup>, tu tires quelles conclusions/recommandations ? Pour moi le programme a une mauvaise conception <sup id="fnref-2-OTMtraLxN"><a href="#fn-2-OTMtraLxN" class="footnote-ref">2</a></sup>.</p>
</blockquote><figcaption><a href="https://zestedesavoir.com/forums/sujet/12577/cette-classe-est-elle-un-sous-type-legitime/?page=2#p204423">Freedom</a></figcaption></figure>
<p>J’ai pas de réponses. Il n’est pas si simple de dire que le système est mal conçu. Ou alors pour mal conçu, on donne l’idée "quand on n’a pas fait une preuve, c’est mal conçu" <img src="/static/smileys/langue.png" alt=":P" class="smiley"></p>Cette classe est-elle un sous type légitime ?, message #2044232019-06-12T11:51:44+02:00Freedom/@Freedomhttps://zestedesavoir.com/forums/sujet/12577/cette-classe-est-elle-un-sous-type-legitime/?page=2#p204423<blockquote>
<p>Ah mais attention ! Je ne dis pas que la situation que je décris est souhaitable, ni que le développeur prend nécessairement en compte ces infos</p>
</blockquote>
<p>Le départ de la discussion c’était quand même de savoir quand il est souhaitable de considérer qu’un type est un sous-type viable, si tu arrives a une situation ou tu rejettes un sous-type tout en disant que le raisonnement ayant conduit au rejet n’est pas souhaitable, je trouve ça un peu paradoxale <img src="/static/smileys/smile.png" alt=":)" class="smiley"> .</p>
<blockquote>
<p>Typiquement, on pourrait avoir une situation où une propriété implicite d’un objet est absolument nécessaire à un programme sans pour autant que cela soit voulu explicitement par le développeur.</p>
</blockquote>
<p>Lorsque cette situation arrive <sup id="fnref-1-ZuFdYpOOd"><a href="#fn-1-ZuFdYpOOd" class="footnote-ref">1</a></sup>, tu tires quelles conclusions/recommandations ? Pour moi le programme a une mauvaise conception <sup id="fnref-2-ZuFdYpOOd"><a href="#fn-2-ZuFdYpOOd" class="footnote-ref">2</a></sup>. </p>
<blockquote>
<p>Et le jour où on ajoute un nouveau type censément correct, parce qu’il ne respecte pas une propriété implicite, il fait exploser du code existant. Et à mon sens, le problème est bien là.</p>
</blockquote>
<p>Certes, sauf que dans ce cas j’incrimine plus le code existant : il explose uniquement parce-qu’il se base sur une propriété implicite. Or, idéalement, c’est en amont que cette utilisation d’une propriété implicite aurait du être identifiée et le code rejeté (donc bien en amont de toute substitution <sup id="fnref-3-ZuFdYpOOd"><a href="#fn-3-ZuFdYpOOd" class="footnote-ref">3</a></sup>).</p>
<p>Je ne dis pas que le problème que tu exposes n’en est pas un, loin de la, simplement que — pour moi — ce n’est pas le sens du LSP.</p>
<p><sup id="fnref-1-ZuFdYpOOd"><a href="#fn-1-ZuFdYpOOd" class="footnote-ref">1</a></sup> Je ne dis pas que c’est simple d’identifier ou de prouver de telles propriétés (ça je te laisse le soin de juger^^).</p>
<p><sup id="fnref-2-ZuFdYpOOd"><a href="#fn-2-ZuFdYpOOd" class="footnote-ref">2</a></sup> Sans que ce soit le LSP qui rentre nécessairement en jeu.</p>
<p><sup id="fnref-3-ZuFdYpOOd"><a href="#fn-3-ZuFdYpOOd" class="footnote-ref">3</a></sup> Et c’est une façon de voir que ce n’est pas le LSP qui est pris a défaut : le problème de conception est la avant la substitution, i.e. le code a déjà "explose" avant même que l’idée d’une substitution ne germe.</p>Cette classe est-elle un sous type légitime ?, message #2044222019-06-12T11:06:15+02:00Ksass`Peuk/@Ksass%60Peukhttps://zestedesavoir.com/forums/sujet/12577/cette-classe-est-elle-un-sous-type-legitime/?page=2#p204422<p>Ah mais attention ! Je ne dis pas que la situation que je décris est souhaitable, ni que le développeur prend nécessairement en compte ces infos. Mais à force de faire de la preuve, ce dont je me rends compte, c’est que justement ces situations d’imprécision sont très dangereuses.</p>
<p>Typiquement, on pourrait avoir une situation où une propriété implicite d’un objet est absolument nécessaire à un programme sans pour autant que cela soit voulu explicitement par le développeur. Et pour les propriétés temporelles c’est affreux, parce que ça peut vraiment se planquer. Et le jour où on ajoute un nouveau type censément correct, parce qu’il ne respecte pas une propriété implicite, il fait exploser du code existant. Et à mon sens, le problème est bien là.</p>Cette classe est-elle un sous type légitime ?, message #2044212019-06-12T10:07:33+02:00Freedom/@Freedomhttps://zestedesavoir.com/forums/sujet/12577/cette-classe-est-elle-un-sous-type-legitime/?page=2#p204421<p>Ok, donc on est en effet en désaccord sur le fond vraiment, pour moi le LSP n’est pas violé dans ce cas — qui est plus simple et direct, comme tu le dis, et c’est bien pour ça que je le proposais : se mettre d’accord (ou non) sur un cas simple avant d’ajouter de la complexité.</p>
<p>Pour moi la propriété implicite que tu identifies (i > 0) et est brisée par la classe fille n’est qu’un détail d’implémentation et ne doit pas rentrer en compte pour le LSP.</p>
<p>Je vois le LSP avant tout comme un outil pratique entre deux personnes : </p>
<ul>
<li>Le fournisseur du type d’origine et son interface; </li>
<li>L’utilisateur du type d’origine et créateur de sous-types; </li>
</ul>
<p>L’objectif étant de laisser le plus de liberté aux deux personnes. Et c’est la qu’intervient les contrats : Le fournisseur donne un ensemble de contrats sur son interface et en échange du respect des contrats par l’utilisateur il assure une invariance des comportements dans les limites des contrats. Le LSP la dedans revient juste a dire que les contrats des interfaces des sous-types doivent être au moins aussi flexible en utilisation et au moins aussi précis sur les attentes. La conséquence est que l’utilisateur a la liberté d’ouvrir le contrat et le fournisseur la liberté de l’implémentation dans le cadre du contrat.</p>
<p>Ici j’ai donné en commentaire les spécifications, et de ce point de vu le sous-type les respect et le type de base assure bien un comportement correct. La propriété que tu identifies ne fait pas parti du contrat, pour moi elle ne doit pas être considérée, le faire revient a contraindre la liberté du fournisseur plus que ce qu’il t’a promis.</p>
<p>Et je peux pousser un peu, disons que la classe mère propose un algo <code>foo</code> et ce qu’il faut en <code>protected</code> pour que tu puisses refaire l’algo dans une classe fille. Le fournisseur te spécifie que l’algo doit avoir une complexité en temps au pire quadratique. Or il se trouve que son implémentation est quadratique (et que tu peux le prouver). Je ne vois vraiment pas le gain a considérer — en vertus du LSP — que tu n’as pas le droit de redéfinir cet algo dans un sous-type avec un temps logarithmique que tu aurais découvert. Et, même sans le <code>protected</code>, ça interdit au fournisseur d’améliorer son algorithme !</p>
<p>Et dans le fond la propriété temporelle dont tu parlais au départ est de ce genre : tu la déduis<sup id="fnref-1-wwOvlFmMjO"><a href="#fn-1-wwOvlFmMjO" class="footnote-ref">1</a></sup> des pré/post et de l’interface que tu considères comme invariante <sup id="fnref-2-wwOvlFmMjO"><a href="#fn-2-wwOvlFmMjO" class="footnote-ref">2</a></sup>. Or cette invariance me semble être une contrainte beaucoup trop forte. C’est une propriété vrai en l’état mais qui n’est qu’une coïncidence a ne pas considérer comme une propriété (et donc idem pour les propriétés temporelles que tu déduis depuis ça). Par contre, pour le cas de départ, si le fournisseur donne la spécification explicite:</p>
<blockquote>
<p>Si le compteur devient négatif il le reste</p>
</blockquote>
<p>La <code>mul</code> brise le LSP. Je suis donc d’accord que les pre/post sur les messages ne suffisent pas, mais je maintiens que le cas présenté ici ne brise pas nécessairement le LSP.</p>
<p>Pour résumer, je pense comprendre ce point de vue, mais cette vision du LSP est pour moi beaucoup trop restrictive et plus néfaste qu’utile pour la conception d’un programme. Si j’accepte cette définition du LSP, je suis d’accord qu’il est violé dans les cas qu’on a considéré. Mais je trouve cette définition inutile en pratique.</p>
<p><sup id="fnref-1-wwOvlFmMjO"><a href="#fn-1-wwOvlFmMjO" class="footnote-ref">1</a></sup> D’ailleurs c’est aussi ce que fait le toy-model que j’ai présente plus haut, il faudrait que je rajoute explicitement les post-conditions quelque-part.<br>
<sup id="fnref-2-wwOvlFmMjO"><a href="#fn-2-wwOvlFmMjO" class="footnote-ref">2</a></sup> Directement, le fournisseur de la classe de base ne peut pas rajouter <code>mul</code> dans une future itération. Ou indirectement, il n’y a rien de <code>protected</code> qui permet d’étendre l’interface. </p>Cette classe est-elle un sous type légitime ?, message #2044132019-06-12T09:20:45+02:00Ksass`Peuk/@Ksass%60Peukhttps://zestedesavoir.com/forums/sujet/12577/cette-classe-est-elle-un-sous-type-legitime/?page=1#p204413<figure><blockquote>
<p>Est-ce que dans cette situation le LSP est violé ?</p>
</blockquote><figcaption><a href="https://zestedesavoir.com/forums/sujet/12577/cette-classe-est-elle-un-sous-type-legitime/?page=1#p204406">Freedom</a></figcaption></figure>
<p>(Je ne prétends pas avoir la réponse au problème posé, simplement que tous les éléments temporels sont plus subtils qu’il n’y paraissent à mon avis et que si on autorise le mot clé protected/public le respect des contraintes sur les pré et post-conditions me semble léger pour maintenir des propriétés temporelles. C’est d’ailleurs pour ça que je trouve qu’il est généralement une mauvaise pratique d’avoir des propriétés temporelles sur les objets pour les appels de fonctions membres, et encore plus quand on autorise la dérivation).</p>
<figure><blockquote>
<p>Est-ce que dans cette situation le LSP est violé ?</p>
</blockquote><figcaption><a href="https://zestedesavoir.com/forums/sujet/12577/cette-classe-est-elle-un-sous-type-legitime/?page=1#p204406">Freedom</a></figcaption></figure>
<p>C’est effectivement aussi une violation, plus directe, mais également due à une propriété cachée (implicitement foo assure i positif, mais sa surcharge non). Et en fait, ce qui est intéressant une nouvelle fois c’est que le problème ne va apparaître que si le développeur a fait des suppositions supplémentaires sur le programme. </p>
<p>Ici on peut raisonnablement considérer que les contrats sont imprécis. Mais sur les propriétés temporelles, on ne peut pas spécifier si simplement ce qui rend ce genre d’imprécisions encore mieux planquées. Il y a une différence qui est assez importante entre cet exemple et le premier. On ne peut pas si facilement expliciter une propriété temporelle et il est encore plus difficile de la vérifier.</p>Cette classe est-elle un sous type légitime ?, message #2044062019-06-11T19:56:39+02:00Freedom/@Freedomhttps://zestedesavoir.com/forums/sujet/12577/cette-classe-est-elle-un-sous-type-legitime/?page=1#p204406<p>Ok, je crois que je vois mieux où est le problème selon toi. Prenons le cas suivant (c’est pas exactement la même chose, mais j’y vois un lien) :</p>
<div class="hljs-code-div"><div class="hljs-line-numbers"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></div><pre><code class="hljs language-cpp"><span class="hljs-class"><span class="hljs-keyword">struct</span> <span class="hljs-title">A</span> {</span>
<span class="hljs-comment">//require i >= 0</span>
<span class="hljs-comment">//ensure i <= 0</span>
<span class="hljs-comment">//ensure abs(i) == old(i) </span>
<span class="hljs-function"><span class="hljs-keyword">virtual</span> <span class="hljs-keyword">void</span> <span class="hljs-title">bar</span><span class="hljs-params">()</span> </span>{
i = -i;
}
<span class="hljs-comment">//ensure i >= 0</span>
<span class="hljs-comment">//ensure i == old(i*i)</span>
<span class="hljs-function"><span class="hljs-keyword">virtual</span> <span class="hljs-keyword">void</span> <span class="hljs-title">goo</span><span class="hljs-params">()</span> </span>{
i = i*i;
}
<span class="hljs-comment">//ensure abs(i) == old(i*i)</span>
<span class="hljs-function"><span class="hljs-keyword">virtual</span> <span class="hljs-keyword">void</span> <span class="hljs-title">foo</span><span class="hljs-params">()</span> </span>{
<span class="hljs-keyword">this</span>->goo();
}
<span class="hljs-keyword">private</span>:
<span class="hljs-keyword">int</span> i;
};
<span class="hljs-class"><span class="hljs-keyword">struct</span> <span class="hljs-title">B</span> :</span> A {
<span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">foo</span><span class="hljs-params">()</span> </span>{
<span class="hljs-keyword">this</span>->goo()
<span class="hljs-keyword">this</span>->bar()
}
};
</code></pre></div>
<p>Est-ce que dans cette situation le LSP est violé ?</p>Cette classe est-elle un sous type légitime ?, message #2044002019-06-11T17:39:26+02:00Ksass`Peuk/@Ksass%60Peukhttps://zestedesavoir.com/forums/sujet/12577/cette-classe-est-elle-un-sous-type-legitime/?page=1#p204400<figure><blockquote>
<p>Je ne vois pas ce qui change dans ton exemple, je peux toujours pas remplacer <code>Bar in_fact_bar ;</code> par <code>Foo in_fact_bar ;</code> (je fais pas attention au ref/pointeur, c’est un detail technique pour cette discussion). </p>
</blockquote><figcaption><a href="https://zestedesavoir.com/forums/sujet/12577/cette-classe-est-elle-un-sous-type-legitime/?page=1#p204398">Freedom</a></figcaption></figure>
<p>C’est pas ce que je fais non. J’ai bien remplacé une référence vers un objet d’un certain type par un objet qui est censé être d’un sous-type de ce type. À moins que l’ajout de mul casse le LSP, c’est une opération valide, j’ai le droit de changer cet objet.</p>
<figure><blockquote>
<p>C’est ensuite le LSP qui vient rajouter la contrainte <strong>le comportement, en terme de pré et post condition, doit être le même</strong>.</p>
</blockquote><figcaption><a href="https://zestedesavoir.com/forums/sujet/12577/cette-classe-est-elle-un-sous-type-legitime/?page=1#p204398">Freedom</a></figcaption></figure>
<p>Oui mais justement c’est la question de départ : est ce que cette contrainte en terme de pré/post est suffisante pour garantir que ça marche pour des propriétés temporelles. Et clairement, non puisque tu contraints les remplacements à ne s’effectuer que sur des traces qui ne changent pas lorsqu’il y a sous-typage. Ce qui, du fait que l’on ne remplace pas forcément qu’un objet à la fois dans un programme, est une condition forte : il faut non seulement vérifier le LSP localement mais aussi globalement à travers les traces générées par d’autres objets.</p>
<p>En haut, la trace de base est changée par la conjonction de deux remplacements. En gros : c’est Derived qui casse le LSP sur Other, en proposant un objet qui temporellement peut redevenir positif. Seulement, vu que ce comportement cassé à travers Bar qui prétend remplacer parfaitement Foo, qui est vraiment le fautif ?</p>Cette classe est-elle un sous type légitime ?, message #2043982019-06-11T17:25:45+02:00Freedom/@Freedomhttps://zestedesavoir.com/forums/sujet/12577/cette-classe-est-elle-un-sous-type-legitime/?page=1#p204398<p>Je ne vois pas ce qui change dans ton exemple, je peux toujours pas remplacer <code>Bar in_fact_bar ;</code> par <code>Foo in_fact_bar ;</code> (je fais pas attention au ref/pointeur, c’est un detail technique pour cette discussion). C’est sur cette ligne qu’est le LSP pour moi.</p>
<p>Tu as raté la partie <em>implémentation</em> dans le formalisme que je montre. Il ne m’interdit pas d’écrire :</p>
<div class="hljs-code-div"><div class="hljs-line-numbers"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></div><pre><code class="hljs language-cpp"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Foo</span> {</span>
<span class="hljs-keyword">public</span>:
<span class="hljs-comment">/*@
requires this->val >= 0
ensures this->val > \old(this->val) ;
*/</span>
<span class="hljs-function"><span class="hljs-keyword">virtual</span> <span class="hljs-keyword">void</span> <span class="hljs-title">incr</span><span class="hljs-params">()</span></span>;
<span class="hljs-comment">/*@
ensures this->val < \old(this->val) ;
*/</span>
<span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">decr</span><span class="hljs-params">()</span></span>;
};
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Bar</span> :</span> <span class="hljs-keyword">public</span> Foo {
<span class="hljs-keyword">public</span>:
<span class="hljs-comment">/*@
ensures this->val == \old(this->val) * x ;
*/</span>
<span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">mul</span><span class="hljs-params">(<span class="hljs-keyword">int</span> x)</span> </span>;
<span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">incr</span><span class="hljs-params">()</span>
</span>{ <span class="hljs-keyword">this</span>->mul(<span class="hljs-number">-2</span>); }
}
</code></pre></div>
<p>J’ajoute une fonction mul et je l’utilise. Par contre ça casse le LSP.</p>
<p>Avec des mots, une protocole c’est juste une suite de noms, de message, auquel l’objet répond. Par exemple la suite <code>foo,bar,foo,foo,bar</code>, tout ce que je dis c’est que pour considérer le LSP tu dois déjà avoir deux types tel que les objets de ces types répondent a ce protocole <strong>peu importe comment</strong> (c’est le sens de la note [1]). C’est ensuite le LSP qui vient rajouter la contrainte <strong>le comportement, en terme de pré et post condition, doit être le même</strong>.</p>
<p>Dis autrement, pour moi, le LSP n’intervient qu’a partir du moment ou:</p>
<div class="hljs-code-div"><div class="hljs-line-numbers"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></div><pre><code class="hljs language-cpp"><span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">lsp_test</span><span class="hljs-params">(base& b)</span> </span>{
<span class="hljs-comment">//Suite d'instructions sans structure de contrôle</span>
<span class="hljs-comment">//C'est la suite de message</span>
}
base b;
derived d;
lsp_test(b);
lsp_test(d);
</code></pre></div>
<p>Est valide.</p>
<p>Or je n’ai pas l’impression que le cas considéré ici puisse être écrit de cette manière.</p>
<p>Edit: Pour le morceau que tu as mis en gras, on est bien d’accord que je considère cette substitution fille -> mère uniquement pour la discussion du LSP. Je ne considère pas ça comme nécessaire de manière générale. Je ne trouve pas ça si fort, la formulation du LSP — peu importe laquelle — est toujours de la forme:</p>
<blockquote>
<p>Si xxx sur mere alors xxx sur fille</p>
</blockquote>
<p>On parle donc d’un implication, et tout ce que je dis c’est que pour discuter de cette implication c’est mieux d’être dans le cas ou l’antécédent est vrai. Ça te semble vraiment fort comme condition ?</p>Cette classe est-elle un sous type légitime ?, message #2043972019-06-11T17:06:40+02:00Ksass`Peuk/@Ksass%60Peukhttps://zestedesavoir.com/forums/sujet/12577/cette-classe-est-elle-un-sous-type-legitime/?page=1#p204397<figure><blockquote>
<p>Pour reprendre ce que tu viens de dire <strong>lorsque l’on change un objet pour son sous-type</strong> ca implique quand meme que <strong>si je remplace le sous-type (dans les situations ou le LSP est d’intérêt — ce qui est sensé être le cas dans nos exemples, sinon l’exemple n’est plus pertinent pour le LSP) par le type mère, le code doit rester valable — puisque c’est le type mère qui définit le contrat de départ</strong>. Or si tu peux remplacer un éventuel <code>Derived o ;</code> par <code>Other o ;</code>, tu ne peux pas remplacer <code>Bar m_bar ;</code> par <code>Foo m_bar ;</code> dans l’exemple ici.</p>
</blockquote><figcaption><a href="https://zestedesavoir.com/forums/sujet/12577/cette-classe-est-elle-un-sous-type-legitime/?page=1#p204396">Freedom</a></figcaption></figure>
<p>C’était pour simplifier l’exemple. J’ai tout à fait le droit d’écrire :</p>
<div class="hljs-code-div"><div class="hljs-line-numbers"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></div><pre><code class="hljs language-cpp"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Other</span> {</span>
<span class="hljs-keyword">public</span>:
Other(){
m_foo = &actual_foo ;
}
<span class="hljs-keyword">protected</span>:
Foo* m_foo ;
Foo actual_foo ;
};
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Derived</span> {</span>
<span class="hljs-keyword">public</span>:
Other(){
m_foo = &in_fact_bar ;
}
<span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">up_2</span><span class="hljs-params">()</span></span>{
in_fact_bar.mul(<span class="hljs-number">-2</span>);
}
<span class="hljs-keyword">protected</span>:
Bar in_fact_bar ;
};
</code></pre></div>
<p>Ce code ne présente pas de remplacement qui soit invalide. Avant m_foo référençait un Foo, maintenant il référence un Bar qui est censé être un sous-type. Sauf que de fait on peut faire un appel qui l’empêche d’avoir la propriété temporelle de son sur-type.</p>
<p>Concernant ton morceau de formalisation, le problème est amha que tu supposes que si l’on remplace un objet alors nécessairement le protocole qu’on lui applique restera le même. Et ça me semble une contrainte hyper forte. En particulier dans le morceau que j’ai mis en gras, c’est une contrainte très forte. Ça veut dire qu’un objet enfant ne peut soit jamais ajouter de méthodes, soit jamais passer par un contexte où l’on a une meilleure connaissance de son type.</p>
<p>Il n’y a pas a priori de raison de dire que l’on ne peut pas faire ce remplacement, sauf à dire que les méthodes appelable de l’objet ne comprennent pas <code>mul</code> (ce qui revient à interdire l’usage de toute méthode ajoutée), ou à interdire protected qui rend le LSP safe même sur une propriété temporelle de manière à peu près triviale je pense.</p>Cette classe est-elle un sous type légitime ?, message #2043962019-06-11T16:28:30+02:00Freedom/@Freedomhttps://zestedesavoir.com/forums/sujet/12577/cette-classe-est-elle-un-sous-type-legitime/?page=1#p204396<p>Pour formaliser un peu plus <sup id="fnref-1-Q9beeGRJwx"><a href="#fn-1-Q9beeGRJwx" class="footnote-ref">1</a></sup>. Si je note :</p>
<ul>
<li><span class="inlineMath"><span class="katex"><span class="katex-mathml"><math><semantics><mrow><msub><mi>S</mi><mi>T</mi></msub></mrow><annotation>S_T</annotation></semantics></math></span><span class="katex-html"><span class="base"><span class="strut" style="height:0.83333em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathdefault" style="margin-right:0.05764em;">S</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.32833099999999993em;"><span style="top:-2.5500000000000003em;margin-left:-0.05764em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathdefault mtight" style="margin-right:0.13889em;">T</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span></span> l’ensemble des états <em>possibles</em> <sup id="fnref-2-Q9beeGRJwx"><a href="#fn-2-Q9beeGRJwx" class="footnote-ref">2</a></sup> d’un type <span class="inlineMath"><span class="katex"><span class="katex-mathml"><math><semantics><mrow><mi>T</mi></mrow><annotation>T</annotation></semantics></math></span><span class="katex-html"><span class="base"><span class="strut" style="height:0.68333em;vertical-align:0em;"></span><span class="mord mathdefault" style="margin-right:0.13889em;">T</span></span></span></span></span>, et <span class="inlineMath"><span class="katex"><span class="katex-mathml"><math><semantics><mrow><mi>o</mi><mo>∈</mo><msub><mi>S</mi><mi>T</mi></msub></mrow><annotation>o\in S_T</annotation></semantics></math></span><span class="katex-html"><span class="base"><span class="strut" style="height:0.5782em;vertical-align:-0.0391em;"></span><span class="mord mathdefault">o</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span><span class="mrel">∈</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span></span><span class="base"><span class="strut" style="height:0.83333em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathdefault" style="margin-right:0.05764em;">S</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.32833099999999993em;"><span style="top:-2.5500000000000003em;margin-left:-0.05764em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathdefault mtight" style="margin-right:0.13889em;">T</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span></span> un objet de type <span class="inlineMath"><span class="katex"><span class="katex-mathml"><math><semantics><mrow><mi>T</mi></mrow><annotation>T</annotation></semantics></math></span><span class="katex-html"><span class="base"><span class="strut" style="height:0.68333em;vertical-align:0em;"></span><span class="mord mathdefault" style="margin-right:0.13889em;">T</span></span></span></span></span>;</li>
<li><span class="inlineMath"><span class="katex"><span class="katex-mathml"><math><semantics><mrow><mi>U</mi><mi>∣</mi><mi>T</mi></mrow><annotation>U|T</annotation></semantics></math></span><span class="katex-html"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathdefault" style="margin-right:0.10903em;">U</span><span class="mord">∣</span><span class="mord mathdefault" style="margin-right:0.13889em;">T</span></span></span></span></span> la relation de sous-typage (en particulier <span class="inlineMath"><span class="katex"><span class="katex-mathml"><math><semantics><mrow><mi>T</mi><mi>∣</mi><mi>T</mi></mrow><annotation>T|T</annotation></semantics></math></span><span class="katex-html"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathdefault" style="margin-right:0.13889em;">T</span><span class="mord">∣</span><span class="mord mathdefault" style="margin-right:0.13889em;">T</span></span></span></span></span>) et <span class="inlineMath"><span class="katex"><span class="katex-mathml"><math><semantics><mrow><mi>S</mi></mrow><annotation>\mathcal{S}</annotation></semantics></math></span><span class="katex-html"><span class="base"><span class="strut" style="height:0.68333em;vertical-align:0em;"></span><span class="mord"><span class="mord mathcal" style="margin-right:0.075em;">S</span></span></span></span></span></span> qui associe a un objet et un de ses sur-types la partie de son état associée a ce sur-type, i.e.
<span class="inlineMath inlineMathDouble"><span class="katex-display"><span class="katex"><span class="katex-mathml"><math><semantics><mrow><mi>S</mi><mo>:</mo><mi>o</mi><mo>∈</mo><msub><mi>S</mi><mi>U</mi></msub><mo>,</mo><mi>U</mi><mi>∣</mi><mi>T</mi><mo>↦</mo><mi>S</mi><mrow><mo>(</mo><mi>o</mi><mo>,</mo><mi>T</mi><mo>)</mo></mrow><mo>∈</mo><msub><mi>S</mi><mi>T</mi></msub></mrow><annotation>\mathcal{S} : o\in S_U,U|T \mapsto \mathcal{S}\left(o,T\right) \in{S_T}</annotation></semantics></math></span><span class="katex-html"><span class="base"><span class="strut" style="height:0.68333em;vertical-align:0em;"></span><span class="mord"><span class="mord mathcal" style="margin-right:0.075em;">S</span></span><span class="mspace" style="margin-right:0.2777777777777778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span></span><span class="base"><span class="strut" style="height:0.5782em;vertical-align:-0.0391em;"></span><span class="mord mathdefault">o</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span><span class="mrel">∈</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord mathdefault" style="margin-right:0.05764em;">S</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.32833099999999993em;"><span style="top:-2.5500000000000003em;margin-left:-0.05764em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathdefault mtight" style="margin-right:0.10903em;">U</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.16666666666666666em;"></span><span class="mord mathdefault" style="margin-right:0.10903em;">U</span><span class="mord">∣</span><span class="mord mathdefault" style="margin-right:0.13889em;">T</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span><span class="mrel">↦</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord mathcal" style="margin-right:0.075em;">S</span></span><span class="mspace" style="margin-right:0.16666666666666666em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord mathdefault">o</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.16666666666666666em;"></span><span class="mord mathdefault" style="margin-right:0.13889em;">T</span><span class="mclose delimcenter" style="top:0em;">)</span></span><span class="mspace" style="margin-right:0.2777777777777778em;"></span><span class="mrel">∈</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span></span><span class="base"><span class="strut" style="height:0.83333em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord"><span class="mord mathdefault" style="margin-right:0.05764em;">S</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.32833099999999993em;"><span style="top:-2.5500000000000003em;margin-left:-0.05764em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathdefault mtight" style="margin-right:0.13889em;">T</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span></span></span></span></li>
<li><span class="inlineMath"><span class="katex"><span class="katex-mathml"><math><semantics><mrow><msub><mi>M</mi><mi>T</mi></msub></mrow><annotation>M_T</annotation></semantics></math></span><span class="katex-html"><span class="base"><span class="strut" style="height:0.83333em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathdefault" style="margin-right:0.10903em;">M</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.32833099999999993em;"><span style="top:-2.5500000000000003em;margin-left:-0.10903em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathdefault mtight" style="margin-right:0.13889em;">T</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span></span> l’ensemble des messages associés au type <span class="inlineMath"><span class="katex"><span class="katex-mathml"><math><semantics><mrow><mi>T</mi></mrow><annotation>T</annotation></semantics></math></span><span class="katex-html"><span class="base"><span class="strut" style="height:0.68333em;vertical-align:0em;"></span><span class="mord mathdefault" style="margin-right:0.13889em;">T</span></span></span></span></span> et <span class="inlineMath"><span class="katex"><span class="katex-mathml"><math><semantics><mrow><mi>I</mi></mrow><annotation>\mathcal{I}</annotation></semantics></math></span><span class="katex-html"><span class="base"><span class="strut" style="height:0.68333em;vertical-align:0em;"></span><span class="mord"><span class="mord mathcal" style="margin-right:0.07382em;">I</span></span></span></span></span></span> la fonction associant a une message et un type son implémentation — i.e.
<span class="inlineMath inlineMathDouble"><span class="katex-display"><span class="katex"><span class="katex-mathml"><math><semantics><mrow><mi>I</mi><mo>:</mo><mi>m</mi><mo>∈</mo><msub><mi>M</mi><mi>T</mi></msub><mo>,</mo><mi>U</mi><mi>∣</mi><mi>T</mi><mo>↦</mo><mi>I</mi><mrow><mo>(</mo><mi>m</mi><mo>,</mo><mi>U</mi><mo>)</mo></mrow><mo>∈</mo><msup><msub><mi>S</mi><mi>U</mi></msub><msub><mi>S</mi><mi>U</mi></msub></msup></mrow><annotation>\mathcal{I} : m\in M_T,U|T \mapsto \mathcal{I}\left(m,U\right) \in{S_U}^{S_U}</annotation></semantics></math></span><span class="katex-html"><span class="base"><span class="strut" style="height:0.68333em;vertical-align:0em;"></span><span class="mord"><span class="mord mathcal" style="margin-right:0.07382em;">I</span></span><span class="mspace" style="margin-right:0.2777777777777778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span></span><span class="base"><span class="strut" style="height:0.5782em;vertical-align:-0.0391em;"></span><span class="mord mathdefault">m</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span><span class="mrel">∈</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord mathdefault" style="margin-right:0.10903em;">M</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.32833099999999993em;"><span style="top:-2.5500000000000003em;margin-left:-0.10903em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathdefault mtight" style="margin-right:0.13889em;">T</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.16666666666666666em;"></span><span class="mord mathdefault" style="margin-right:0.10903em;">U</span><span class="mord">∣</span><span class="mord mathdefault" style="margin-right:0.13889em;">T</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span><span class="mrel">↦</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord mathcal" style="margin-right:0.07382em;">I</span></span><span class="mspace" style="margin-right:0.16666666666666666em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord mathdefault">m</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.16666666666666666em;"></span><span class="mord mathdefault" style="margin-right:0.10903em;">U</span><span class="mclose delimcenter" style="top:0em;">)</span></span><span class="mspace" style="margin-right:0.2777777777777778em;"></span><span class="mrel">∈</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span></span><span class="base"><span class="strut" style="height:1.0645609999999999em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord"><span class="mord"><span class="mord mathdefault" style="margin-right:0.05764em;">S</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.32833099999999993em;"><span style="top:-2.5500000000000003em;margin-left:-0.05764em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathdefault mtight" style="margin-right:0.10903em;">U</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.914561em;"><span style="top:-3.1362300000000003em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight"><span class="mord mathdefault mtight" style="margin-right:0.05764em;">S</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.3448em;"><span style="top:-2.3567071428571427em;margin-left:-0.05764em;margin-right:0.07142857142857144em;"><span class="pstrut" style="height:2.5em;"></span><span class="sizing reset-size3 size1 mtight"><span class="mord mathdefault mtight" style="margin-right:0.10903em;">U</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.14329285714285717em;"><span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></span></li>
<li><span class="inlineMath"><span class="katex"><span class="katex-mathml"><math><semantics><mrow><msub><mi>V</mi><mi>T</mi></msub></mrow><annotation>V_T</annotation></semantics></math></span><span class="katex-html"><span class="base"><span class="strut" style="height:0.83333em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathdefault" style="margin-right:0.22222em;">V</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.32833099999999993em;"><span style="top:-2.5500000000000003em;margin-left:-0.22222em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathdefault mtight" style="margin-right:0.13889em;">T</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span></span> l’ensemble des propriétés caractérisant un objet de type <span class="inlineMath"><span class="katex"><span class="katex-mathml"><math><semantics><mrow><mi>T</mi></mrow><annotation>T</annotation></semantics></math></span><span class="katex-html"><span class="base"><span class="strut" style="height:0.68333em;vertical-align:0em;"></span><span class="mord mathdefault" style="margin-right:0.13889em;">T</span></span></span></span></span>, cad l’appartenance de cet objet a un sous-ensemble des états possible — les états caractérises par cette propriété — i.e. <span class="inlineMath"><span class="katex"><span class="katex-mathml"><math><semantics><mrow><msub><mi>V</mi><mi>T</mi></msub><mo>≡</mo><mi>P</mi><mrow><mo>(</mo><msub><mi>S</mi><mi>T</mi></msub><mo>)</mo></mrow></mrow><annotation>V_T\equiv \mathcal{P}\left(S_T\right)</annotation></semantics></math></span><span class="katex-html"><span class="base"><span class="strut" style="height:0.83333em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathdefault" style="margin-right:0.22222em;">V</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.32833099999999993em;"><span style="top:-2.5500000000000003em;margin-left:-0.22222em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathdefault mtight" style="margin-right:0.13889em;">T</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2777777777777778em;"></span><span class="mrel">≡</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord mathcal" style="margin-right:0.08222em;">P</span></span><span class="mspace" style="margin-right:0.16666666666666666em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord"><span class="mord mathdefault" style="margin-right:0.05764em;">S</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.32833099999999993em;"><span style="top:-2.5500000000000003em;margin-left:-0.05764em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathdefault mtight" style="margin-right:0.13889em;">T</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose delimcenter" style="top:0em;">)</span></span></span></span></span></span>, et pour une propriété <span class="inlineMath"><span class="katex"><span class="katex-mathml"><math><semantics><mrow><mi>p</mi><mo>∈</mo><msub><mi>V</mi><mi>T</mi></msub></mrow><annotation>p\in V_T</annotation></semantics></math></span><span class="katex-html"><span class="base"><span class="strut" style="height:0.7335400000000001em;vertical-align:-0.19444em;"></span><span class="mord mathdefault">p</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span><span class="mrel">∈</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span></span><span class="base"><span class="strut" style="height:0.83333em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathdefault" style="margin-right:0.22222em;">V</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.32833099999999993em;"><span style="top:-2.5500000000000003em;margin-left:-0.22222em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathdefault mtight" style="margin-right:0.13889em;">T</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span></span> on note <span class="inlineMath"><span class="katex"><span class="katex-mathml"><math><semantics><mrow><mi>v</mi><mo>(</mo><mi>o</mi><mo>)</mo></mrow><annotation>v(o)</annotation></semantics></math></span><span class="katex-html"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathdefault" style="margin-right:0.03588em;">v</span><span class="mopen">(</span><span class="mord mathdefault">o</span><span class="mclose">)</span></span></span></span></span> la valeur de vérité de cette propriété sur un objet <span class="inlineMath"><span class="katex"><span class="katex-mathml"><math><semantics><mrow><mi>o</mi><mo>∈</mo><msub><mi>S</mi><mrow><mi>U</mi><mi>∣</mi><mi>T</mi></mrow></msub></mrow><annotation>o\in S_{U|T}</annotation></semantics></math></span><span class="katex-html"><span class="base"><span class="strut" style="height:0.5782em;vertical-align:-0.0391em;"></span><span class="mord mathdefault">o</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span><span class="mrel">∈</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span></span><span class="base"><span class="strut" style="height:1.03853em;vertical-align:-0.3551999999999999em;"></span><span class="mord"><span class="mord mathdefault" style="margin-right:0.05764em;">S</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.34480000000000005em;"><span style="top:-2.5198em;margin-left:-0.05764em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathdefault mtight" style="margin-right:0.10903em;">U</span><span class="mord mtight">∣</span><span class="mord mathdefault mtight" style="margin-right:0.13889em;">T</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.3551999999999999em;"><span></span></span></span></span></span></span></span></span></span></span>, i.e. <span class="inlineMath"><span class="katex"><span class="katex-mathml"><math><semantics><mrow><mi>v</mi><mo>(</mo><mi>o</mi><mo>)</mo><mo>≡</mo><mi>S</mi><mrow><mo>(</mo><mi>o</mi><mo>,</mo><mi>T</mi><mo>)</mo></mrow><mo>∈</mo><mi>v</mi></mrow><annotation>v(o)\equiv \mathcal{S}\left(o,T\right)\in v</annotation></semantics></math></span><span class="katex-html"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathdefault" style="margin-right:0.03588em;">v</span><span class="mopen">(</span><span class="mord mathdefault">o</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span><span class="mrel">≡</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord mathcal" style="margin-right:0.075em;">S</span></span><span class="mspace" style="margin-right:0.16666666666666666em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord mathdefault">o</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.16666666666666666em;"></span><span class="mord mathdefault" style="margin-right:0.13889em;">T</span><span class="mclose delimcenter" style="top:0em;">)</span></span><span class="mspace" style="margin-right:0.2777777777777778em;"></span><span class="mrel">∈</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span></span><span class="base"><span class="strut" style="height:0.43056em;vertical-align:0em;"></span><span class="mord mathdefault" style="margin-right:0.03588em;">v</span></span></span></span></span>.</li>
</ul>
<p>A partir de la je construis deux choses:</p>
<ul>
<li><span class="inlineMath"><span class="katex"><span class="katex-mathml"><math><semantics><mrow><msub><mi>P</mi><mi>T</mi></msub></mrow><annotation>P_T</annotation></semantics></math></span><span class="katex-html"><span class="base"><span class="strut" style="height:0.83333em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathdefault" style="margin-right:0.13889em;">P</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.32833099999999993em;"><span style="top:-2.5500000000000003em;margin-left:-0.13889em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathdefault mtight" style="margin-right:0.13889em;">T</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span></span> l’ensemble des des protocoles valables associés au type <span class="inlineMath"><span class="katex"><span class="katex-mathml"><math><semantics><mrow><mi>T</mi></mrow><annotation>T</annotation></semantics></math></span><span class="katex-html"><span class="base"><span class="strut" style="height:0.68333em;vertical-align:0em;"></span><span class="mord mathdefault" style="margin-right:0.13889em;">T</span></span></span></span></span> — i.e <span class="inlineMath"><span class="katex"><span class="katex-mathml"><math><semantics><mrow><msub><mi>P</mi><mi>T</mi></msub><mo>⊂</mo><msubsup><mi>M</mi><mi>T</mi><mi>N</mi></msubsup></mrow><annotation>P_T \subset M_T^{\mathbb{N}}</annotation></semantics></math></span><span class="katex-html"><span class="base"><span class="strut" style="height:0.83333em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathdefault" style="margin-right:0.13889em;">P</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.32833099999999993em;"><span style="top:-2.5500000000000003em;margin-left:-0.13889em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathdefault mtight" style="margin-right:0.13889em;">T</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2777777777777778em;"></span><span class="mrel">⊂</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span></span><span class="base"><span class="strut" style="height:1.1205539999999998em;vertical-align:-0.275331em;"></span><span class="mord"><span class="mord mathdefault" style="margin-right:0.10903em;">M</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.845223em;"><span style="top:-2.424669em;margin-left:-0.10903em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathdefault mtight" style="margin-right:0.13889em;">T</span></span></span><span style="top:-3.063em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight"><span class="mord mathbb mtight">N</span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.275331em;"><span></span></span></span></span></span></span></span></span></span></span>, et pour un protocole valable <span class="inlineMath"><span class="katex"><span class="katex-mathml"><math><semantics><mrow><mi>p</mi><mo>=</mo><msub><mrow><mo>(</mo><msub><mi>m</mi><mi>n</mi></msub><mo>∈</mo><msub><mi>M</mi><mi>T</mi></msub><mo>)</mo></mrow><mrow><mi>n</mi><mo>∈</mo><mi>N</mi></mrow></msub><mo>∈</mo><msub><mi>P</mi><mi>T</mi></msub></mrow><annotation>p = \left(m_n\in M_T\right)_{n\in\mathbb{N}} \in P_T</annotation></semantics></math></span><span class="katex-html"><span class="base"><span class="strut" style="height:0.625em;vertical-align:-0.19444em;"></span><span class="mord mathdefault">p</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span><span class="mrel">=</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span></span><span class="base"><span class="strut" style="height:1.07707em;vertical-align:-0.32706999999999997em;"></span><span class="minner"><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord"><span class="mord mathdefault">m</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.151392em;"><span style="top:-2.5500000000000003em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathdefault mtight">n</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2777777777777778em;"></span><span class="mrel">∈</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span><span class="mord"><span class="mord mathdefault" style="margin-right:0.10903em;">M</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.32833099999999993em;"><span style="top:-2.5500000000000003em;margin-left:-0.10903em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathdefault mtight" style="margin-right:0.13889em;">T</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mclose delimcenter" style="top:0em;">)</span></span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.182523em;"><span style="top:-2.4003em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathdefault mtight">n</span><span class="mrel mtight">∈</span><span class="mord mtight"><span class="mord mathbb mtight">N</span></span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.32706999999999997em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2777777777777778em;"></span><span class="mrel">∈</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span></span><span class="base"><span class="strut" style="height:0.83333em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathdefault" style="margin-right:0.13889em;">P</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.32833099999999993em;"><span style="top:-2.5500000000000003em;margin-left:-0.13889em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathdefault mtight" style="margin-right:0.13889em;">T</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span></span> et un objet <span class="inlineMath"><span class="katex"><span class="katex-mathml"><math><semantics><mrow><mi>o</mi><mo>∈</mo><mi>U</mi><mi>∣</mi><mi>T</mi></mrow><annotation>o\in U|T</annotation></semantics></math></span><span class="katex-html"><span class="base"><span class="strut" style="height:0.5782em;vertical-align:-0.0391em;"></span><span class="mord mathdefault">o</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span><span class="mrel">∈</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathdefault" style="margin-right:0.10903em;">U</span><span class="mord">∣</span><span class="mord mathdefault" style="margin-right:0.13889em;">T</span></span></span></span></span> on note <span class="inlineMath"><span class="katex"><span class="katex-mathml"><math><semantics><mrow><mi>p</mi><mo>(</mo><mi>o</mi><mo>)</mo></mrow><annotation>p(o)</annotation></semantics></math></span><span class="katex-html"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathdefault">p</span><span class="mopen">(</span><span class="mord mathdefault">o</span><span class="mclose">)</span></span></span></span></span> l’état a l’issu du protocole, i.e. <span class="inlineMath"><span class="katex"><span class="katex-mathml"><math><semantics><mrow><mi>p</mi><mo>(</mo><mi>o</mi><mo>)</mo><mo>≡</mo><msub><mi>lim</mi><mo></mo><mrow><mi>n</mi><mo>→</mo><mi>∞</mi></mrow></msub><mi>I</mi><mrow><mo>(</mo><msub><mi>m</mi><mi>n</mi></msub><mo>,</mo><mi>U</mi><mo>)</mo></mrow><mo>∘</mo><mo>⋯</mo><mo>∘</mo><mi>I</mi><mrow><mo>(</mo><msub><mi>m</mi><mn>0</mn></msub><mo>,</mo><mi>U</mi><mo>)</mo></mrow><mo>(</mo><mi>o</mi><mo>)</mo></mrow><annotation>p(o)\equiv \lim_{n\rightarrow\infty} \mathcal{I}\left(m_n,U\right)\circ\dots\circ \mathcal{I}\left(m_0,U\right)(o)</annotation></semantics></math></span><span class="katex-html"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathdefault">p</span><span class="mopen">(</span><span class="mord mathdefault">o</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span><span class="mrel">≡</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mop"><span class="mop">lim</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.151392em;"><span style="top:-2.5500000000000003em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathdefault mtight">n</span><span class="mrel mtight">→</span><span class="mord mtight">∞</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.16666666666666666em;"></span><span class="mord"><span class="mord mathcal" style="margin-right:0.07382em;">I</span></span><span class="mspace" style="margin-right:0.16666666666666666em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord"><span class="mord mathdefault">m</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.151392em;"><span style="top:-2.5500000000000003em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathdefault mtight">n</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.16666666666666666em;"></span><span class="mord mathdefault" style="margin-right:0.10903em;">U</span><span class="mclose delimcenter" style="top:0em;">)</span></span><span class="mspace" style="margin-right:0.2222222222222222em;"></span><span class="mbin">∘</span><span class="mspace" style="margin-right:0.2222222222222222em;"></span></span><span class="base"><span class="strut" style="height:0.44445em;vertical-align:0em;"></span><span class="minner">⋯</span><span class="mspace" style="margin-right:0.2222222222222222em;"></span><span class="mbin">∘</span><span class="mspace" style="margin-right:0.2222222222222222em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord mathcal" style="margin-right:0.07382em;">I</span></span><span class="mspace" style="margin-right:0.16666666666666666em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord"><span class="mord mathdefault">m</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.30110799999999993em;"><span style="top:-2.5500000000000003em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight">0</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.16666666666666666em;"></span><span class="mord mathdefault" style="margin-right:0.10903em;">U</span><span class="mclose delimcenter" style="top:0em;">)</span></span><span class="mspace" style="margin-right:0.16666666666666666em;"></span><span class="mopen">(</span><span class="mord mathdefault">o</span><span class="mclose">)</span></span></span></span></span> <sup id="fnref-3-Q9beeGRJwx"><a href="#fn-3-Q9beeGRJwx" class="footnote-ref">3</a></sup>;</li>
<li><span class="inlineMath"><span class="katex"><span class="katex-mathml"><math><semantics><mrow><msub><mi>C</mi><mi>T</mi></msub><mo>≡</mo><msub><mi>V</mi><mi>T</mi></msub><mo>,</mo><msub><mi>C</mi><mi>T</mi></msub></mrow><annotation>\mathcal{C}_T \equiv \mathcal{V}_T,C_T</annotation></semantics></math></span><span class="katex-html"><span class="base"><span class="strut" style="height:0.83333em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord"><span class="mord mathcal" style="margin-right:0.05834em;">C</span></span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.32833099999999993em;"><span style="top:-2.5500000000000003em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathdefault mtight" style="margin-right:0.13889em;">T</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2777777777777778em;"></span><span class="mrel">≡</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span></span><span class="base"><span class="strut" style="height:0.8777699999999999em;vertical-align:-0.19444em;"></span><span class="mord"><span class="mord"><span class="mord mathcal" style="margin-right:0.08222em;">V</span></span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.32833099999999993em;"><span style="top:-2.5500000000000003em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathdefault mtight" style="margin-right:0.13889em;">T</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.16666666666666666em;"></span><span class="mord"><span class="mord mathdefault" style="margin-right:0.07153em;">C</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.32833099999999993em;"><span style="top:-2.5500000000000003em;margin-left:-0.07153em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathdefault mtight" style="margin-right:0.13889em;">T</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span></span> le contrat du type <span class="inlineMath"><span class="katex"><span class="katex-mathml"><math><semantics><mrow><mi>T</mi></mrow><annotation>T</annotation></semantics></math></span><span class="katex-html"><span class="base"><span class="strut" style="height:0.68333em;vertical-align:0em;"></span><span class="mord mathdefault" style="margin-right:0.13889em;">T</span></span></span></span></span>, la première qui a un protocole associe un ensemble de propriétés — les pré-conditions possibles. Et la seconde qui a un protocole et un type — l’implémentation — associe une map entre les pré-conditions et un autre ensemble de propriétés — les post-conditions correspondantes :
<span class="inlineMath inlineMathDouble"><span class="katex-display"><span class="katex"><span class="katex-mathml"><math><semantics><mrow><msub><mi>V</mi><mi>T</mi></msub><mo>:</mo><mi>p</mi><mo>∈</mo><msub><mi>P</mi><mi>T</mi></msub><mo>↦</mo><msub><mi>V</mi><mi>T</mi></msub><mrow><mo>(</mo><mi>p</mi><mo>)</mo></mrow><mo>⊂</mo><msub><mi>V</mi><mi>T</mi></msub></mrow><annotation>\mathcal{V}_T : p\in P_T \mapsto \mathcal{V}_T\left(p\right)\subset V_T</annotation></semantics></math></span><span class="katex-html"><span class="base"><span class="strut" style="height:0.83333em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord"><span class="mord mathcal" style="margin-right:0.08222em;">V</span></span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.32833099999999993em;"><span style="top:-2.5500000000000003em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathdefault mtight" style="margin-right:0.13889em;">T</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2777777777777778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span></span><span class="base"><span class="strut" style="height:0.7335400000000001em;vertical-align:-0.19444em;"></span><span class="mord mathdefault">p</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span><span class="mrel">∈</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span></span><span class="base"><span class="strut" style="height:0.83333em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathdefault" style="margin-right:0.13889em;">P</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.32833099999999993em;"><span style="top:-2.5500000000000003em;margin-left:-0.13889em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathdefault mtight" style="margin-right:0.13889em;">T</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2777777777777778em;"></span><span class="mrel">↦</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span></span><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord"><span class="mord mathcal" style="margin-right:0.08222em;">V</span></span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.32833099999999993em;"><span style="top:-2.5500000000000003em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathdefault mtight" style="margin-right:0.13889em;">T</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.16666666666666666em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord mathdefault">p</span><span class="mclose delimcenter" style="top:0em;">)</span></span><span class="mspace" style="margin-right:0.2777777777777778em;"></span><span class="mrel">⊂</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span></span><span class="base"><span class="strut" style="height:0.83333em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathdefault" style="margin-right:0.22222em;">V</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.32833099999999993em;"><span style="top:-2.5500000000000003em;margin-left:-0.22222em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathdefault mtight" style="margin-right:0.13889em;">T</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span></span></span></span></span></span>
<span class="inlineMath inlineMathDouble"><span class="katex-display"><span class="katex"><span class="katex-mathml"><math><semantics><mrow><msub><mi>C</mi><mi>T</mi></msub><mo>:</mo><mi>p</mi><mo>∈</mo><msub><mi>P</mi><mi>T</mi></msub><mo>,</mo><mi>U</mi><mi>∣</mi><mi>T</mi><mtext> </mtext><mo>↦</mo><mtext> </mtext><mrow><mo>[</mo><msup><mi>v</mi><mo>′</mo></msup><mo>∈</mo><msub><mi>V</mi><mi>T</mi></msub><mo>(</mo><mi>p</mi><mo>)</mo><mo>↦</mo><mrow><mo>{</mo><mi>S</mi><mrow><mo>(</mo><mi>p</mi><mo>(</mo><mi>o</mi><mo>)</mo><mo>,</mo><mi>T</mi><mo>)</mo></mrow><mtext> </mtext><mi>∣</mi><mtext> </mtext><mi>o</mi><mo>∈</mo><mi>U</mi><mtext> et </mtext><msup><mi>v</mi><mo>′</mo></msup><mo>(</mo><mi>o</mi><mo>)</mo><mo>}</mo></mrow><mo>]</mo></mrow></mrow><annotation>C_T : p\in P_T,U|T~\mapsto~\left[ v^{\prime}\in\mathcal{V}_T(p) \mapsto \left\{\mathcal{S}\left(p(o),T\right)~|~o\in U \text{ et } v^{\prime}(o)\right\} \right]</annotation></semantics></math></span><span class="katex-html"><span class="base"><span class="strut" style="height:0.83333em;vertical-align:-0.15em;"></span><span class="mord"><span class="mord mathdefault" style="margin-right:0.07153em;">C</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.32833099999999993em;"><span style="top:-2.5500000000000003em;margin-left:-0.07153em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathdefault mtight" style="margin-right:0.13889em;">T</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2777777777777778em;"></span><span class="mrel">:</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span></span><span class="base"><span class="strut" style="height:0.7335400000000001em;vertical-align:-0.19444em;"></span><span class="mord mathdefault">p</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span><span class="mrel">∈</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span></span><span class="base"><span class="strut" style="height:1.051892em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord mathdefault" style="margin-right:0.13889em;">P</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.32833099999999993em;"><span style="top:-2.5500000000000003em;margin-left:-0.13889em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathdefault mtight" style="margin-right:0.13889em;">T</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.16666666666666666em;"></span><span class="mord mathdefault" style="margin-right:0.10903em;">U</span><span class="mord">∣</span><span class="mord mathdefault" style="margin-right:0.13889em;">T</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span><span class="mspace nobreak"> </span><span class="mrel">↦</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span><span class="mspace nobreak"> </span><span class="minner"><span class="mopen delimcenter" style="top:0em;">[</span><span class="mord"><span class="mord mathdefault" style="margin-right:0.03588em;">v</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.801892em;"><span style="top:-3.113em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">′</span></span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2777777777777778em;"></span><span class="mrel">∈</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span><span class="mord"><span class="mord"><span class="mord mathcal" style="margin-right:0.08222em;">V</span></span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.32833099999999993em;"><span style="top:-2.5500000000000003em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathdefault mtight" style="margin-right:0.13889em;">T</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mopen">(</span><span class="mord mathdefault">p</span><span class="mclose">)</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span><span class="mrel">↦</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">{</span><span class="mord"><span class="mord mathcal" style="margin-right:0.075em;">S</span></span><span class="mspace" style="margin-right:0.16666666666666666em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord mathdefault">p</span><span class="mopen">(</span><span class="mord mathdefault">o</span><span class="mclose">)</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.16666666666666666em;"></span><span class="mord mathdefault" style="margin-right:0.13889em;">T</span><span class="mclose delimcenter" style="top:0em;">)</span></span><span class="mspace" style="margin-right:0.16666666666666666em;"></span><span class="mspace nobreak"> </span><span class="mord">∣</span><span class="mspace nobreak"> </span><span class="mord mathdefault">o</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span><span class="mrel">∈</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span><span class="mord mathdefault" style="margin-right:0.10903em;">U</span><span class="mord text"><span class="mord"> et </span></span><span class="mord"><span class="mord mathdefault" style="margin-right:0.03588em;">v</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.801892em;"><span style="top:-3.113em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">′</span></span></span></span></span></span></span></span></span><span class="mopen">(</span><span class="mord mathdefault">o</span><span class="mclose">)</span><span class="mclose delimcenter" style="top:0em;">}</span></span><span class="mclose delimcenter" style="top:0em;">]</span></span></span></span></span></span></span></li>
</ul>
<p>A partit de la, le LSP s’écrit pour moi:
<span class="inlineMath inlineMathDouble"><span class="katex-display"><span class="katex"><span class="katex-mathml"><math><semantics><mrow><mi>U</mi><mtext> </mtext><msub><mi>∣</mi><mrow><mi>L</mi><mi>S</mi><mi>P</mi></mrow></msub><mtext> </mtext><mi>T</mi><mtext> </mtext><mo>⟺</mo><mtext> </mtext><mi>∀</mi><mi>p</mi><mo>∈</mo><msub><mi>P</mi><mi>T</mi></msub><mo>,</mo><mtext> </mtext><mi>∀</mi><msup><mi>v</mi><mo>′</mo></msup><mo>∈</mo><msub><mi>V</mi><mi>T</mi></msub><mo>(</mo><mi>p</mi><mo>)</mo><mo>,</mo><mtext> </mtext><msub><mi>C</mi><mi>T</mi></msub><mrow><mo>(</mo><mi>p</mi><mo>,</mo><mi>U</mi><mo>)</mo></mrow><mrow><mo>(</mo><msup><mi>v</mi><mo>′</mo></msup><mo>)</mo></mrow><mo>⊂</mo><msub><mi>C</mi><mi>T</mi></msub><mrow><mo>(</mo><mi>p</mi><mo>,</mo><mi>T</mi><mo>)</mo></mrow><mrow><mo>(</mo><msup><mi>v</mi><mo>′</mo></msup><mo>)</mo></mrow></mrow><annotation>U~|_{LSP}~T \iff \forall p\in P_T,~\forall v^{\prime}\in\mathcal{V}_T(p),~C_T\left(p,U\right)\left(v^{\prime}\right) \subset C_T\left(p,T\right)\left(v^{\prime}\right)</annotation></semantics></math></span><span class="katex-html"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mord mathdefault" style="margin-right:0.10903em;">U</span><span class="mspace nobreak"> </span><span class="mord"><span class="mord">∣</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.32833099999999993em;"><span style="top:-2.5500000000000003em;margin-left:0em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mathdefault mtight">L</span><span class="mord mathdefault mtight" style="margin-right:0.05764em;">S</span><span class="mord mathdefault mtight" style="margin-right:0.13889em;">P</span></span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace nobreak"> </span><span class="mord mathdefault" style="margin-right:0.13889em;">T</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span><span class="mspace" style="margin-right:0.2777777777777778em;"></span><span class="mrel">⟺</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span><span class="mspace" style="margin-right:0.2777777777777778em;"></span></span><span class="base"><span class="strut" style="height:0.8888799999999999em;vertical-align:-0.19444em;"></span><span class="mord">∀</span><span class="mord mathdefault">p</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span><span class="mrel">∈</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span></span><span class="base"><span class="strut" style="height:0.996332em;vertical-align:-0.19444em;"></span><span class="mord"><span class="mord mathdefault" style="margin-right:0.13889em;">P</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.32833099999999993em;"><span style="top:-2.5500000000000003em;margin-left:-0.13889em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathdefault mtight" style="margin-right:0.13889em;">T</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.16666666666666666em;"></span><span class="mspace nobreak"> </span><span class="mord">∀</span><span class="mord"><span class="mord mathdefault" style="margin-right:0.03588em;">v</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.801892em;"><span style="top:-3.113em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">′</span></span></span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.2777777777777778em;"></span><span class="mrel">∈</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span></span><span class="base"><span class="strut" style="height:1.051892em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord"><span class="mord mathcal" style="margin-right:0.08222em;">V</span></span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.32833099999999993em;"><span style="top:-2.5500000000000003em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathdefault mtight" style="margin-right:0.13889em;">T</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mopen">(</span><span class="mord mathdefault">p</span><span class="mclose">)</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.16666666666666666em;"></span><span class="mspace nobreak"> </span><span class="mord"><span class="mord mathdefault" style="margin-right:0.07153em;">C</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.32833099999999993em;"><span style="top:-2.5500000000000003em;margin-left:-0.07153em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathdefault mtight" style="margin-right:0.13889em;">T</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.16666666666666666em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord mathdefault">p</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.16666666666666666em;"></span><span class="mord mathdefault" style="margin-right:0.10903em;">U</span><span class="mclose delimcenter" style="top:0em;">)</span></span><span class="mspace" style="margin-right:0.16666666666666666em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord"><span class="mord mathdefault" style="margin-right:0.03588em;">v</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.801892em;"><span style="top:-3.113em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">′</span></span></span></span></span></span></span></span></span><span class="mclose delimcenter" style="top:0em;">)</span></span><span class="mspace" style="margin-right:0.2777777777777778em;"></span><span class="mrel">⊂</span><span class="mspace" style="margin-right:0.2777777777777778em;"></span></span><span class="base"><span class="strut" style="height:1.051892em;vertical-align:-0.25em;"></span><span class="mord"><span class="mord mathdefault" style="margin-right:0.07153em;">C</span><span class="msupsub"><span class="vlist-t vlist-t2"><span class="vlist-r"><span class="vlist" style="height:0.32833099999999993em;"><span style="top:-2.5500000000000003em;margin-left:-0.07153em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mathdefault mtight" style="margin-right:0.13889em;">T</span></span></span></span><span class="vlist-s"></span></span><span class="vlist-r"><span class="vlist" style="height:0.15em;"><span></span></span></span></span></span></span><span class="mspace" style="margin-right:0.16666666666666666em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord mathdefault">p</span><span class="mpunct">,</span><span class="mspace" style="margin-right:0.16666666666666666em;"></span><span class="mord mathdefault" style="margin-right:0.13889em;">T</span><span class="mclose delimcenter" style="top:0em;">)</span></span><span class="mspace" style="margin-right:0.16666666666666666em;"></span><span class="minner"><span class="mopen delimcenter" style="top:0em;">(</span><span class="mord"><span class="mord mathdefault" style="margin-right:0.03588em;">v</span><span class="msupsub"><span class="vlist-t"><span class="vlist-r"><span class="vlist" style="height:0.801892em;"><span style="top:-3.113em;margin-right:0.05em;"><span class="pstrut" style="height:2.7em;"></span><span class="sizing reset-size6 size3 mtight"><span class="mord mtight"><span class="mord mtight">′</span></span></span></span></span></span></span></span></span><span class="mclose delimcenter" style="top:0em;">)</span></span></span></span></span></span></span></p>
<p><sup id="fnref-1-Q9beeGRJwx"><a href="#fn-1-Q9beeGRJwx" class="footnote-ref">1</a></sup> Vous m’excuserez les notations probablement pas usuel, je n’ai pas les outils formels usuels.<br>
<sup id="fnref-2-Q9beeGRJwx"><a href="#fn-2-Q9beeGRJwx" class="footnote-ref">2</a></sup> Ici possible n’implique pas accessible.<br>
<sup id="fnref-3-Q9beeGRJwx"><a href="#fn-3-Q9beeGRJwx" class="footnote-ref">3</a></sup> La convergence est supposée.</p>
<p>Edit: Je n’ai pas lu ta dernière réponse avant d’edit pour ne pas me laisser influencer par ton message.
Edit2: Simplification d’une relation.</p>
<blockquote>
<p>Mais le principe du LSP est de garantir que tout est interchangeable en s’assurant que le contrat reste respecté lorsque l’on change un objet pour son sous-type.</p>
</blockquote>
<p>Ça je pense qu’on est tous d’accord que c’est bien l’objectif du LSP.</p>
<p>Le code en entier (pour reprendre) :</p>
<div class="hljs-code-div"><div class="hljs-line-numbers"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></div><pre><code class="hljs language-cpp"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Foo</span> {</span>
<span class="hljs-keyword">public</span>:
<span class="hljs-comment">/*@
requires this->val >= 0
ensures this->val > \old(this->val) ;
*/</span>
<span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">incr</span><span class="hljs-params">()</span></span>;
<span class="hljs-comment">/*@
ensures this->val < \old(this->val) ;
*/</span>
<span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">decr</span><span class="hljs-params">()</span></span>;
};
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Bar</span> :</span> <span class="hljs-keyword">public</span> Foo {
<span class="hljs-keyword">public</span>:
<span class="hljs-comment">/*@
ensures this->val == \old(this->val) * x ;
*/</span>
<span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">mul</span><span class="hljs-params">(<span class="hljs-keyword">int</span> x)</span> </span>;
}
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Other</span> {</span>
<span class="hljs-keyword">public</span>:
Other();
<span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">up_1</span><span class="hljs-params">()</span></span>{ m_foo.dec(); }
<span class="hljs-function"><span class="hljs-keyword">virtual</span> <span class="hljs-keyword">void</span> <span class="hljs-title">up_2</span><span class="hljs-params">()</span></span>;
<span class="hljs-function"><span class="hljs-keyword">virtual</span> Foo& <span class="hljs-title">get</span><span class="hljs-params">()</span></span>{ <span class="hljs-keyword">return</span> m_foo ; }
<span class="hljs-keyword">private</span>:
Foo m_foo ;
};
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Derived</span> :</span> <span class="hljs-keyword">public</span> Other {
<span class="hljs-keyword">public</span>:
<span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">up_2</span><span class="hljs-params">()</span></span>{ m_bar.mul(<span class="hljs-number">-2</span>); }
<span class="hljs-function">Foo& <span class="hljs-title">get</span><span class="hljs-params">()</span> </span>{ <span class="hljs-keyword">return</span> m_bar ; }
<span class="hljs-keyword">private</span>:
Bar m_bar ;
};
Other o ;
<span class="hljs-keyword">while</span>(o.get().is_positive()){
o.up_1();
}
<span class="hljs-comment">//ici l'objet obtenu est censé ne plus pouvoir être positif</span>
o.up_2();
</code></pre></div>
<p>Pour reprendre ce que tu viens de dire <strong>lorsque l’on change un objet pour son sous-type</strong> ca implique quand meme que si je remplace le sous-type (dans les situations ou le LSP est d’intérêt — ce qui est sensé être le cas dans nos exemples, sinon l’exemple n’est plus pertinent pour le LSP) par le type mère, le code doit rester valable — puisque c’est le type mère qui définit le contrat de départ. Or si tu peux remplacer un éventuel <code>Derived o ;</code> par <code>Other o ;</code>, tu ne peux pas remplacer <code>Bar m_bar ;</code> par <code>Foo m_bar ;</code> dans l’exemple ici.</p>Cette classe est-elle un sous type légitime ?, message #2043922019-06-11T14:08:56+02:00Ksass`Peuk/@Ksass%60Peukhttps://zestedesavoir.com/forums/sujet/12577/cette-classe-est-elle-un-sous-type-legitime/?page=1#p204392<figure><blockquote>
<p>Pourquoi tu conclus à cette interdiction ? Pour moi ton code respecte le LSP, alors que tu penses que non, j’ai du mal à voir en quoi je suis plus restrictif du coup !?</p>
</blockquote><figcaption><a href="https://zestedesavoir.com/forums/sujet/12577/cette-classe-est-elle-un-sous-type-legitime/?page=1#p204389">Freedom</a></figcaption></figure>
<p>D’accord. Je vois mieux. </p>
<p>Mais le principe du LSP est de garantir que tout est interchangeable en s’assurant que le contrat reste respecté lorsque l’on change un objet pour son sous-type. Or ici, ce n’est pas le cas : j’ai changé un objet (en l’occurrence deux) pour des objets de sous-types et ma propriété finale (externe) ne tient plus. Si par exemple j’avais un programme qui récupérait la valeur de l’objet pour un appel qui a comme précondition que la valeur est négative, la précondition de l’appel en question serait cassée, ce qui par respect du LSP ne devrait pas pouvoir arriver.</p>Cette classe est-elle un sous type légitime ?, message #2043902019-06-11T13:14:42+02:00pierre_24/@pierre_24https://zestedesavoir.com/forums/sujet/12577/cette-classe-est-elle-un-sous-type-legitime/?page=1#p204390<div class="custom-block custom-block-spoiler"><div class="custom-block-body"><figure><blockquote>
<p>Si je reformule un peu j’ai l’impression que la formulation du LSP que tu supposes ressemble à :</p>
<blockquote>
<p>Toute propriété valable sur un objet d’un type doit l’être sur les objets d’un sous-type.</p>
</blockquote>
</blockquote><figcaption><a href="https://zestedesavoir.com/forums/sujet/12577/cette-classe-est-elle-un-sous-type-legitime/?page=1#p204389">Freedom</a></figcaption></figure><p>(pour info, c’est <a href="https://zestedesavoir.com/forums/sujet/12577/cette-classe-est-elle-un-sous-type-legitime/?page=1#p204258">aussi ma version du LSP</a>)</p></div></div>Cette classe est-elle un sous type légitime ?, message #2043892019-06-11T12:25:02+02:00Freedom/@Freedomhttps://zestedesavoir.com/forums/sujet/12577/cette-classe-est-elle-un-sous-type-legitime/?page=1#p204389<p>Pourquoi tu conclus à cette interdiction ? Pour moi ton code respecte le LSP, alors que tu penses que non, j’ai du mal à voir en quoi je suis plus restrictif du coup !?</p>
<p>Si je reformule un peu j’ai l’impression que la formulation du LSP que tu supposes ressemble à :</p>
<blockquote>
<p>Toute propriété valable sur un objet d’un type doit l’être sur les objets d’un sous-type.</p>
</blockquote>
<p>Ça me semble au contraire plus restrictif que la formulation que j’évoque qui se contente des protocoles valables sur un objet du type de base — qui sont inclus par la formulation sur l’ensemble des propriétés.</p>Cette classe est-elle un sous type légitime ?, message #2043882019-06-11T12:11:27+02:00Ksass`Peuk/@Ksass%60Peukhttps://zestedesavoir.com/forums/sujet/12577/cette-classe-est-elle-un-sous-type-legitime/?page=1#p204388<p>A ce moment là, on interdit complètement l’appel d’une méthode ajoutée par un objet enfant dans le jeu des appels virtuels. Je veux bien, mais là tu passes sur une situation où tu dois en permanence vérifier une énorme propriété globale. C’est extrêmement restrictif, beaucoup plus que le LSP.</p>Cette classe est-elle un sous type légitime ?, message #2043862019-06-11T11:56:11+02:00Freedom/@Freedomhttps://zestedesavoir.com/forums/sujet/12577/cette-classe-est-elle-un-sous-type-legitime/?page=1#p204386<p>Je suis toujours en désaccord. Je vais développer avec ton exemple complété.</p>
<p>Le contrat de départ (et les protocoles et propriétés que tu peux construire depuis celui-ci) te dis en effet </p>
<blockquote>
<p>Si un objet devient négatif pendant un <em>protocole valable sur</em> <strong>le type de base</strong>, il ne peut plus devenir positif.</p>
</blockquote>
<p>Sauf que ton opération <code>o.up_2()</code> revient au message <code>mul</code> qui est invalide sur un objet du type de base, il ne fait donc pas parti d’un <em>protocole valable sur</em> <strong>le type de base</strong>. Par contre ça concerne bien les lignes 3–5 de ton code pour lequel la propriété que tu as identifié est bien respectée.</p>Cette classe est-elle un sous type légitime ?, message #2043832019-06-11T11:31:35+02:00Ksass`Peuk/@Ksass%60Peukhttps://zestedesavoir.com/forums/sujet/12577/cette-classe-est-elle-un-sous-type-legitime/?page=1#p204383<p>Ok, je vais présenter un petit "contre-exemple" où à mon sens, le fautif n’est pas si facile à trouver (note: je considère que l’on est dans le cas où le champ est protected, sinon c’est effectivement trivial). En conservant les classes précédentes. On peut imaginer deux autres classes utilisatrices suivantes :</p>
<div class="hljs-code-div"><div class="hljs-line-numbers"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></div><pre><code class="hljs language-cpp"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Other</span> {</span>
<span class="hljs-keyword">public</span>:
Other();
<span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">up_1</span><span class="hljs-params">()</span></span>{ m_foo.dec(); }
<span class="hljs-function"><span class="hljs-keyword">virtual</span> <span class="hljs-keyword">void</span> <span class="hljs-title">up_2</span><span class="hljs-params">()</span></span>;
<span class="hljs-function"><span class="hljs-keyword">virtual</span> Foo& <span class="hljs-title">get</span><span class="hljs-params">()</span></span>{ <span class="hljs-keyword">return</span> m_foo ; }
<span class="hljs-keyword">private</span>:
Foo m_foo ;
};
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Derived</span> :</span> <span class="hljs-keyword">public</span> Other {
<span class="hljs-keyword">public</span>:
<span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">up_2</span><span class="hljs-params">()</span></span>{ m_bar.mul(<span class="hljs-number">-2</span>); }
<span class="hljs-function">Foo& <span class="hljs-title">get</span><span class="hljs-params">()</span> </span>{ <span class="hljs-keyword">return</span> m_bar ; }
<span class="hljs-keyword">private</span>:
Bar m_bar ;
};
</code></pre></div>
<p>Et on pourrait avoir un code appelant où il se passe ça :</p>
<div class="hljs-code-div"><div class="hljs-line-numbers"><span></span><span></span><span></span><span></span><span></span><span></span><span></span><span></span></div><pre><code class="hljs language-cpp">Other o ;
<span class="hljs-keyword">while</span>(o.get().is_positive()){
o.up_1();
}
<span class="hljs-comment">//ici l'objet obtenu est censé ne plus pouvoir être positif</span>
o.up_2();
</code></pre></div>
<p>La question qui ne me semble pas si trivial c’est "est ce que c’est le faute de Derived ou de Bar ?". Parce que c’est Bar qui casse un contrat temporel en permettant mul même si c’est Derived qui va déclencher la situation qui casse le contrat au final. Et le problème de cette propriété c’est qu’on ne la voit pas localement.</p>Cette classe est-elle un sous type légitime ?, message #2043302019-06-09T00:06:12+02:00lmghs/@lmghshttps://zestedesavoir.com/forums/sujet/12577/cette-classe-est-elle-un-sous-type-legitime/?page=1#p204330<p>Je tends à rejoindre Freedom. Le LSP va se respecter sur ces protocoles, si un protocole exprimé sur le type parent permet de casser l’objet, l’enfant ni est pour rien (enfin… ce n’est pas un problème de LSP pour moi s’il n’y a aucune violation supplémentaire qui soit locale ou globale — mais que la violation était déjà bien là au niveau parent)</p>
<p>Et si c’est un protocole exclusif au type enfant qui met la pagaille…. (*), je ne tends pas à voir ça comme un problème de LSP, mais un mélange d’OCP non respecté et de mauvaise encapsulation. Probablement un mauvais design in fine. Mais que je ne range pas dans la case LSP, car on ne substitue rien sur un chemin exclusif hors sentiers de l’OCP.</p>
<p>(*) <code>mul</code> n’existait pas au niveau parent, et aucun chemin n’y conduisait.</p>Cette classe est-elle un sous type légitime ?, message #2042952019-06-07T08:48:03+02:00Ksass`Peuk/@Ksass%60Peukhttps://zestedesavoir.com/forums/sujet/12577/cette-classe-est-elle-un-sous-type-legitime/?page=1#p204295<figure><blockquote>
<p>J’ai tendance à voir la formulation usuelle du LSP comme une formulation <em>microscopique</em> permettant d’assurer que </p>
<blockquote>
<p>Tout protocole valable sur un objet d’un type doit rester valable sur un objet d’un sous-type</p>
</blockquote>
<p>Où <em>protocole</em> est à prendre comme synonyme de <em>suite de messages envoyé à l’objet</em>; et <em>rester valable</em> comme <em>le respect des préconditions induit le respect des mêmes post-conditions</em>.</p>
</blockquote><figcaption><a href="https://zestedesavoir.com/forums/sujet/12577/cette-classe-est-elle-un-sous-type-legitime/?page=1#p204282">Freedom</a></figcaption></figure>
<p>C’est en ce sens que je dis que le LSP devient contextuel. Parce que tu ne peux pas présumer depuis la classe de base, ou la classe dérivée en cours de développement, du protocole qui va être appliqué dessus, tu es obligé de connaître ce protocole.</p>
<p>Sauf si :</p>
<figure><blockquote>
<p>Et en ce sens la fonction <code>mul</code> ne change rien à priori : aucun protocole impliquant uniquement les messages valables sur le type de départ (donc <code>incr</code> et <code>decr</code>) ne peut impliquer le message <code>mul</code> — sinon ce protocol n’est plus valable pour un objet du type de départ.</p>
</blockquote><figcaption><a href="https://zestedesavoir.com/forums/sujet/12577/cette-classe-est-elle-un-sous-type-legitime/?page=1#p204282">Freedom</a></figcaption></figure>
<p>Personnellement, c’est la propriété que j’attendrais. Seulement pour ça, on a besoin d’une preuve que pour tout programme sur le type de départ, aucun chemin ne peut permettre d’appeler <code>mul</code> même s’il y a remplacement d’autres objets (en respect du LSP), et autre manipulation du genre. Et autant si je ne vois pas de contre-exemple trivial, je ne vois pas non plus comment construire une preuve que si on respecte tout le temps le LSP alors un tel chemin ne peut pas exister.</p>
<p>EDIT: après, pour être facilement blindé, on peut faire un truc très simple : forcer la règle "tout attribut est privé". De cette manière, <code>mul</code> ne peut pas accéder directement à la valeur interne de sa classe parente et il n’y a plus de question à se poser : elle ne peut plus remplir son contrat. Dans un tel cas, je pense que la preuve est à peu près triviale.</p>Cette classe est-elle un sous type légitime ?, message #2042822019-06-06T19:13:34+02:00Freedom/@Freedomhttps://zestedesavoir.com/forums/sujet/12577/cette-classe-est-elle-un-sous-type-legitime/?page=1#p204282<p>J’ai tendance à voir la formulation usuelle du LSP comme une formulation <em>microscopique</em> permettant d’assurer que </p>
<blockquote>
<p>Tout protocole valable sur un objet d’un type doit rester valable sur un objet d’un sous-type</p>
</blockquote>
<p>Où <em>protocole</em> est à prendre comme synonyme de <em>suite de messages envoyé à l’objet</em>; et <em>rester valable</em> comme <em>le respect des préconditions induit le respect des mêmes post-conditions</em>.</p>
<p>Et en ce sens la fonction <code>mul</code> ne change rien à priori : aucun protocole impliquant uniquement les messages valables sur le type de départ (donc <code>incr</code> et <code>decr</code>) ne peut impliquer le message <code>mul</code> — sinon ce protocol n’est plus valable pour un objet du type de départ.</p>