IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Langage C++ Discussion :

Le changement de visibilité d'une fonction virtuelle est-il un viol du LSP ?


Sujet :

Langage C++

  1. #161
    En attente de confirmation mail

    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Août 2004
    Messages
    1 391
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 33
    Localisation : France, Doubs (Franche Comté)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Août 2004
    Messages : 1 391
    Points : 3 311
    Points
    3 311
    Par défaut
    Citation Envoyé par pseudocode Voir le message
    "What is wanted here is something like the following substitution property: [...]"

    Restons pragmatique et ne donnons pas au LSP des super-pouvoirs qu'il ne devrait pas avoir.
    Ca c'est l'objectif du LSP, pas son énoncé, l'énoncé c'est :
    "Si S est un sous-type de T alors toute propriété démontrable pour tout T-objet est vraie pour tout S-objet"

    Ou alors une définition équivalente donner par Meyers B. avec les invariant, pré et post conditions.

    Et énoncé comme ca ils permettent bien de répondre à l'attente voulu (ce que tu cites).

  2. #162
    Rédacteur
    Avatar de pseudocode
    Homme Profil pro
    Architecte système
    Inscrit en
    Décembre 2006
    Messages
    10 062
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 51
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Architecte système
    Secteur : Industrie

    Informations forums :
    Inscription : Décembre 2006
    Messages : 10 062
    Points : 16 081
    Points
    16 081
    Par défaut
    Citation Envoyé par Flob90 Voir le message
    Ca c'est l'objectif du LSP, pas son énoncé, l'énoncé c'est :
    "Si S est un sous-type de T alors toute propriété démontrable pour tout T-objet est vraie pour tout S-objet"
    Moi, ce que j'en dis, c'est que son objectif est plus important que sa définition formelle.

    Chercher à appliquer cette définition en dehors du cadre voulu par l'auteur (substitution), c'est un truc à se retrouver avec une discussion de 10 pages. D'ailleurs...
    ALGORITHME (n.m.): Méthode complexe de résolution d'un problème simple.

  3. #163
    En attente de confirmation mail

    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Août 2004
    Messages
    1 391
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 33
    Localisation : France, Doubs (Franche Comté)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Août 2004
    Messages : 1 391
    Points : 3 311
    Points
    3 311
    Par défaut
    Oui, mais bon, débattre de quelque chose de théroique sans utiliser la définition c'est pas vraiment utile ...

    Après c'est certain que son utilité c'est quand même de répondre à l'objectif et lorsqu'on code normalement (sans chercher à "se tirer une balle dans le pied" copyright koala ) c'est bien l'objectif qu'on cherche à atteindre, et souvent vérifier ce que tu cites ou vérifier une des formulation théorique revient au même. (vérification souvent rapide, pas besoin de discuter 2h pour savoir qu'un objet de type fleur ne se substitue pas à un objet de type voiture, généralement)

    Mais par exemple dans le cas de la question de départ (ie le changement de visibilité est-il un viol du LSP ?), si on se base juste sur ce que tu as dis et le langage, alors il est respecté, si on se base sur la définition formel il ne l'est pas. (mais la question est un peu trodue, vouloir changer la visibilité dans la hiérarchie c'est quand même pas naturel AMA).

  4. #164
    Expert éminent sénior
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 612
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 612
    Points : 30 612
    Points
    30 612
    Par défaut
    Citation Envoyé par Flob90 Voir le message
    Mais par exemple dans le cas de la question de départ (ie le changement de visibilité est-il un viol du LSP ?), si on se base juste sur ce que tu as dis et le langage, alors il est respecté, si on se base sur la définition formel il ne l'est pas. (mais la question est un peu trodue, vouloir changer la visibilité dans la hiérarchie c'est quand même pas naturel AMA).
    En fait, il faut se souvenir de l'historique de ce débat

    Tout a commencé lorsque quelqu'un a présenté un code dans lequel il voulait faire passer une fonction virtuelle déclarée publique dans la classe de base en accessibilité privée (ou était-ce protégée ) dans la classe dérivée.

    J'ai donc fait remarquer que cette relation d'héritage était fausse en justifiant le fait par le viol de LSP, ce à quoi d'autres ont répondu que LSP n'était pas violé, vu que la norme ne l'interdisait pas explicitement et que le compilateur ne nous éjectait pas.
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

  5. #165
    Membre éclairé Avatar de metagoto
    Profil pro
    Hobbyist programmateur
    Inscrit en
    Juin 2009
    Messages
    646
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : Hobbyist programmateur

    Informations forums :
    Inscription : Juin 2009
    Messages : 646
    Points : 845
    Points
    845
    Par défaut
    Citation Envoyé par koala01 Voir le message
    J'ai donc fait remarquer que cette relation d'héritage était fausse en justifiant le fait par le viol de LSP, ce à quoi d'autres ont répondu que LSP n'était pas violé, vu que la norme ne l'interdisait pas explicitement et que le compilateur ne nous éjectait pas.
    ...et que le programme se comportait normalement dans le cadre d'une substitution. Ce qui permet de répondre à la question initiale:

    Le changement de visibilité d'une fonction virtuelle n'est pas (n'implique pas) un viol du LSP en C++

  6. #166
    Expert éminent sénior
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 612
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 612
    Points : 30 612
    Points
    30 612
    Par défaut
    Citation Envoyé par metagoto Voir le message
    ...et que le programme se comportait normalement dans le cadre d'une substitution. Ce qui permet de répondre à la question initiale:

    Le changement de visibilité d'une fonction virtuelle n'est pas (n'implique pas) un viol du LSP en C++
    C'est bien sur ce point que nous ne sommes plus d'accord.

    Ma thèse est que le comportement attendu est... celui du type dynamique, et donc de la classe dérivée, qui devrait donc te faire savoir que tu ne peux pas invoquer la fonction virtuelle.

    La tienne est de dire que, comme tu manipule un objet "passant pour être du type de base", il est normal que tu puisse invoquer une fonction faisant partie de l'interface publique de ce type.

    Toute mon argumentation tient au fait que le langage réellement utilisé ne doit pas importer dans l'évaluation que l'on peut faire quant au respect de LSP.

    Tu semble de ton coté estimer que, comme C++ ne fait pas attention à cela, tu ne viole pas LSP, mais que, si on avait un langage X ou Y qui présente un mécanisme quelconque destiné à la mise en évidence (et surtout au refus) d'une restriction d'accessibilité, LSP serait bel et bien violé.

    Ma position est qu'un principe n'est jamais à "géométrie variable": Si exceptions il doit admettre, elles doivent être explicitement indiquées
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

  7. #167
    Rédacteur
    Avatar de 3DArchi
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    7 634
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 7 634
    Points : 13 017
    Points
    13 017
    Par défaut
    Citation Envoyé par koala01 Voir le message
    Ma thèse est que le comportement attendu est... celui du type dynamique, et donc de la classe dérivée, qui devrait donc te faire savoir que tu ne peux pas invoquer la fonction virtuelle.
    Comment résoudre cela alors :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    struct base
    {
    public :
    void something()
    {
       do_something();
    }
    private:
    virtual void do_something(){}
    };
    struct derived : public base
    {
    private :
    virtual void do_something()
    {
    }
    };
     
    int main()
    {
        derived d;
        d.something();
     
        return 0;
    }
    Substituer dans base::something, si this est de type dynamique base, alors l'appel à do_something est OK. En revanche lorsque this est de type derived, si on se base sur ton raisonnement, cela viole le LSP ... et pouf, un idiom très utile du C++ qui viole un principe de l'objet

  8. #168
    Expert éminent sénior
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 612
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 612
    Points : 30 612
    Points
    30 612
    Par défaut
    Citation Envoyé par 3DArchi Voir le message
    Comment résoudre cela alors :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    struct base
    {
    public :
    void something()
    {
       do_something();
    }
    private:
    virtual void do_something(){}
    };
    struct derived : public base
    {
    private :
    virtual void do_something()
    {
    }
    };
     
    int main()
    {
        derived d;
        d.something();
     
        return 0;
    }
    Substituer dans base::something, si this est de type dynamique base, alors l'appel à do_something est OK. En revanche lorsque this est de type derived, si on se base sur ton raisonnement, cela viole le LSP ... et pouf, un idiom très utile du C++ qui viole un principe de l'objet
    Absolument pas: c'est la capacité d'appeler something qui est la propriété remarquable ici, absolument pas le fait que le comportement de cette fonction va faire appel à une fonction différente

    Mais tu remarquera cependant que ce sera, effectivement, l'implémentation... du type réel de do_something qui sera exécutée
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

  9. #169
    Rédacteur
    Avatar de 3DArchi
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    7 634
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 7 634
    Points : 13 017
    Points
    13 017
    Par défaut
    Je me suis mal exprimé. Je considère l'expression this->do_something dans base::something. Et je substitue this de type base à un this de type derived. Je me retrouve pas loin du même cas que la question de départ

  10. #170
    Expert éminent sénior
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 612
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 612
    Points : 30 612
    Points
    30 612
    Par défaut
    Citation Envoyé par 3DArchi Voir le message
    Je me suis mal exprimé. Je considère l'expression this->do_something dans base::something. Et je substitue this de type base à un this de type derived. Je me retrouve pas loin du même cas que la question de départ
    Mais réfléchit simplement à ce qui va se passer lorsque tu implémente l'idiôme NVI:

    Tu as deux solutions:

    Soit do_something a été réimplémenté dans la classe dérivée, et il est donc normal que ce soit l'implémentation propre à cette classe que tu appelle réellement.

    Soit do_something n'a pas été réimplémenté, et tu utilisera donc l'implémentation de la classe de base.

    Mais, quoi qu'il en soit, tu es au niveau du "fonctionnement interne" de la classe, et tu es déjà "au delà" du problème de la substituabilité qu'autorise LSP:

    LSP n'est là "que" pour te permettre de déterminer s'il est cohérent de laisser l'utilisateur d'invoquer something au départ de la classe dérivée en faisant éventuellement passer l'objet pour une instance de la classe de base.

    Si la réponse est oui, tu fais simplement un pas assez important en direction d'une décision d'héritage
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

  11. #171
    Membre émérite
    Avatar de white_tentacle
    Profil pro
    Inscrit en
    Novembre 2008
    Messages
    1 505
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2008
    Messages : 1 505
    Points : 2 799
    Points
    2 799
    Par défaut
    Je crois que le raisonnement de 3DArchi, avec lequel je suis d'accord, est le suivant :

    - dans base::something, j'appelle, à cause du dispatch, derived::do_something, qui pourtant est private et que donc je ne pourrais normalement pas appeler. Mais je peux car virtual est indépendant de la visibilité, et que j'ai le droit d'appeler base::do_something

    - dans le sujet de ce topic (changement de visibilité), j'appelle, à cause du dispatch, une fonction derived::f() private, donc que je ne pourrais normalement pas appeler. Mais je peux car virtual est indépendant de la visibilité, et que j'ai le droit d'appeler base::f().

    Exprimé comme ça, la similitude ne te semble pas assez frappante ?

  12. #172
    Rédacteur
    Avatar de 3DArchi
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    7 634
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 7 634
    Points : 13 017
    Points
    13 017
    Par défaut
    Merci de reformuler mes pensées embrumées mais c'était exactement ça. Si je m'en tiens à une approche purement théorique du LSP, alors le NVI viole le LSP dès lors que la fonction virtuelle est privée.

  13. #173
    Expert éminent sénior
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 612
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 612
    Points : 30 612
    Points
    30 612
    Par défaut
    Citation Envoyé par 3DArchi Voir le message
    Merci de reformuler mes pensées embrumées mais c'était exactement ça. Si je m'en tiens à une approche purement théorique du LSP, alors le NVI viole le LSP dès lors que la fonction virtuelle est privée.
    Même pas...

    LSP n'est absolument pas commutatif:

    Il t'oblige à t'assurer que tu retrouve dans une classe dérivée toutes les propriétés de la classe de base, mais cela ne veut absolument pas dire que tu doive retrouver, dans la classe de base, toutes les propriété des classes dérivées

    Cela n'aurait d'ailleurs aucun sens parce que cela invaliderait d'office une grande partie des relations d'héritage que l'on pourrait envisager

    Si tu ne pouvais pas ajouter de comportement à un type dérivé par rapport à un type de base, la notion même de l'héritage n'aurait plus beaucoup de sens

    Par contre, il faut effectivement admettre le fait que l'idiome NVI profite honteusement du "bug" qui empêche le compilateur de prendre l'accessibilité des fonctions virtuelles en compte... Et encore...

    Je me doute bien que je ne couperai pas à une explication de cette remarque de normand, mais j'ai encore du mal à trouver l'expression claire du message que je veux faire passer...

    Promis, ce sera pour une prochaine intervention
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

  14. #174
    Membre éclairé Avatar de metagoto
    Profil pro
    Hobbyist programmateur
    Inscrit en
    Juin 2009
    Messages
    646
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : Hobbyist programmateur

    Informations forums :
    Inscription : Juin 2009
    Messages : 646
    Points : 845
    Points
    845
    Par défaut
    Citation Envoyé par koala01 Voir le message
    LSP n'est absolument pas commutatif:

    Il t'oblige à t'assurer que tu retrouve dans une classe dérivée toutes les propriétés de la classe de base, mais cela ne veut absolument pas dire que tu doive retrouver, dans la classe de base, toutes les propriété des classes dérivées
    Dans LSP il y a Substitution. Il me parait hors sujet de parler de classe dérivée dans l'absolue.

    Que le behavior du programme (ou la provable property) soit changé (infirmée) lorsque la classe dérivée est manipulée par son type statique ne nous intéresse pas ici. On est sensé raisonner uniquement dans le cadre d'une substitution.

    Plusieurs programmes C++ proposés dans cette thread montrent clairement que le LSP n'est pas violé en ce qui les concerne.

  15. #175
    En attente de confirmation mail

    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Août 2004
    Messages
    1 391
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 33
    Localisation : France, Doubs (Franche Comté)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Août 2004
    Messages : 1 391
    Points : 3 311
    Points
    3 311
    Par défaut
    Citation Envoyé par metagoto Voir le message
    Plusieurs programmes C++ proposés dans cette thread montrent clairement que le LSP n'est pas violé en ce qui les concerne.
    En effet, si tu le vérifies avec le C++ alors en effet il n'est pas violé. (cf les exemple au début du sujet de test de substitution)

    Mais si tu effectues la vérification avant de considérer le langage, tu ne peux pas tester la substitution (pas de possibilité de faire de code), d'où la nécessité de l'énoncé formel, qui n'est pas vérifié dans ce cas.

    Et c'est justement, il me semble, ce que koala dit depuis le début, ne pas considérer le langage pour vérifier le LSP.

    Après c'est évident que si tu n'es pas d'accord avec lui sur ce point tu peux arriver à une conclusion totalement différente.

  16. #176
    Membre éclairé Avatar de metagoto
    Profil pro
    Hobbyist programmateur
    Inscrit en
    Juin 2009
    Messages
    646
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations professionnelles :
    Activité : Hobbyist programmateur

    Informations forums :
    Inscription : Juin 2009
    Messages : 646
    Points : 845
    Points
    845
    Par défaut
    Citation Envoyé par Flob90 Voir le message
    Mais si tu effectues la vérification avant de considérer le langage, tu ne peux pas tester la substitution (pas de possibilité de faire de code), d'où la nécessité de l'énoncé formel, qui n'est pas vérifié dans ce cas.
    Sans langage, sans implémentation, je pense qu'on ne peut rien dire du LSP, et plus particulièrement ce qui conduit à enfreindre le principe. On pourra tout au plus tabler sur le fait que le langage choisi in fine supportera une certaine notion de "substitution".

    Je suis d'accord qu'un changement de visibilité est suspect et probablement une mauvaise idée, mais comme on l'a vu, cela ne veut pas dire pour autant que le LSP est violé quelque soit le langage et quelque soit le programme.

  17. #177
    Membre émérite
    Avatar de white_tentacle
    Profil pro
    Inscrit en
    Novembre 2008
    Messages
    1 505
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2008
    Messages : 1 505
    Points : 2 799
    Points
    2 799
    Par défaut
    Citation Envoyé par Flob90 Voir le message
    Mais si tu effectues la vérification avant de considérer le langage, tu ne peux pas tester la substitution (pas de possibilité de faire de code), d'où la nécessité de l'énoncé formel, qui n'est pas vérifié dans ce cas.
    Ce n'est pas le langage qui est important, c'est la manière dont va se faire la substitution. Ceci peut dépendre du langage, mais pas forcément (il me semble que VB.net et C# ont les mêmes règles de substitution, par exemple), et dans tous les cas il est possible de créer un autre langage qui utilisera les mêmes règles.

    Après c'est évident que si tu n'es pas d'accord avec lui sur ce point tu peux arriver à une conclusion totalement différente.
    Je crois que c'est une des raisons des divergences d'opinion, oui, on ne parle pas de la même chose .

  18. #178
    Expert éminent sénior
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 612
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 612
    Points : 30 612
    Points
    30 612
    Par défaut
    Hé bien, commençons par mettre les choses à plat, si tu le souhaite, et par dire exactement de quoi on parle...

    On parle, tout le monde sera d'accord avec cela, des langages (orientés) objets.

    De même, je présumes que tout le monde sera d'accord pour dire que la substitution est la mise en oeuvre "pratique" d'une caractéristique "théorique" appelée la "substituabilité".

    La substituabilité est cette caractéristique qui permet, dans les langages (orientés) objets, d'invoquer une fonction qui attend un type donné d'objet en lui passant un objet d'un autre type sans devoir recourir à la conversion, et en étant sur d'observer un comportement adapté au type réel de l'objet transmis.

    En d'autres termes, la substituabilité est la caractéristique qui permet de profiter, grâce à l'héritage (publique) qui peut exister entre deux types distincts, du polymorphisme.

    Je pense que, jusque là, nous parlons bel et bien de la même chose, autrement, il serait intéressant que tu nous dise de quoi tu parles

    Or, tu constatera que, bien que la manière dont je définis la substituabilité est, en définitive, fort proche de ce que nous dit LSP:
    If for each object o1 of type S there is an object o2 of type T such that for all programs P defined in terms of T, the behavior of P is unchanged when o1 is substituted for o2 then S is a subtype of T.
    Que je traduis, par bonté d'âme:
    Si pour chaque objet o1 de type S il y a un objet o2 de type T tel que pour tout programme P défini en terme de T, le comportement de P est inchangé lorsque l'on substitue o1 à o2, alors S est un sous type de T
    Tu remarqueras:
    1. Que l'on ne fait aucun cas du langage utilisé
    2. Que le principe ne donne aucune exception à la règle... Or, si une règle souffre d'exception, elles seront énoncées en même temps que la règle (ex: la règle pour déterminer si une année est bissextile est composée d'une règle générale (divisible par 4), d'une exception (pas divisible par100) et d'une exception à l'exception (mais divisible par 400) ). On doit donc considérer la règle telle qu'elle est énoncée comme complète.
    J'ai juste un problème avec le terme "inchangé" de l'énoncé, que j'aurais volontiers remplacé par "cohérent" (sans doute parce que je ne suis pas gêné par le fait de l'appliquer en dehors du cadre pour lequel il a été énoncé : le cadre de la programmation par contrat ) , ce qui augmente déjà la portée dans laquelle on peut considérer que le principe est respecté

    Mais, même sorti du cadre de la programmation par contrat (auquel cas il faut, si on veut retourner dans ce cadre particulier, appliquer les règles qui le régissent séparément), le langage n'a absolument pas à intervenir dans la validation du respect du principe.

    Je vais prendre un exemple pour te faire comprendre: Mettons que l'on veuille créer une classe TurboGenerator.

    Comme il s'agit d'une turbine couplée à un générateur (ou est-ce un générateur couplé à une turbine ), que l'on peut, en tout cas, utiliser le turbo générateur aussi bien comme une turbine que comme un générateur, LSP nous dit que TurboGenerator est un sous type de l'un comme de l'autre.

    En C++, il n'y aurait strictement aucun problème: l'héritage multiple est tout à fait autorisé. On peut donc tout à fait considérer que LSP est parfaitement respecté

    Mais, si, juste à coté, tu as quelqu'un qui programme en java, qui n'autorise pas l'héritage multiple, il va te dire qu'il ne peut pas faire hériter TurboGenerator à la fois de Turbin et de Generator...

    Il sera obligé de faire hériter TurboGenerator de Turbin et de lui faire implémenter l'interface de Generator, ou, à l'inverse de faire hériter TurobGenerator de Generator et de lui faire implémenter l'interface de Turbin.

    Pourtant, quelle que soit la solution qu'il choisira, l'autre solution continuera parfaitement à respecter pleinement LSP, et si java acceptait l'héritage multiple, la solution de faire hériter TurboGenerator de Turbin ET de Generator le respecterait aussi.

    Ce qu'il faut comprendre, c'est que, s'il faut respecter, lors de la conception, les restrictions imposées par le langage utilisé et qu'il faut, aussi, respecter les décisions de conception qui ont été prises par ailleurs (le javaiste devra prendre en compte la décision qui aura été prise de transformer Turbin ou Generator en interface), LSP reste tout à fait "au dessus de la mêlée", car, s'il valide une décision (ou du moins qu'il ne l'invalide pas), la décision restera valide pour n'importe quel langage (sous réserve toutefois d'en respecter les restrictions).

    Par contre, s'il invalide une décision prise, le fait que le langage autorise à ne pas prendre cette invalidation en compte ne devrait en aucun cas t'inciter à poursuivre dans cette voie, ne serait-ce que parce que, au final, tu te retrouvera avec des comportements incohérents (ex: le fait que tu puisse invoquer une fonction qui est normalement inaccessible depuis un objet donné "simplement" parce que tu as été "assez bête" pour te mettre dans une situation dans laquelle tu as "oublié" son type réel).
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

  19. #179
    Expert confirmé

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2007
    Messages
    1 895
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Septembre 2007
    Messages : 1 895
    Points : 4 551
    Points
    4 551
    Par défaut
    Citation Envoyé par pseudocode Voir le message
    "What is wanted here is something like the following substitution property: If
    for each object o1 of type S there is an object o2 of type T such that for all
    programs P defined in terms of T, the behavior of P is unchanged when o1 is
    substituted for o2 then S is a subtype of T."

    (Barbara Liskov, “Data Abstraction and Hierarchy", 1988)

    Restons pragmatique et ne donnons pas au LSP des super-pouvoirs qu'il ne devrait pas avoir.
    Si Liskov était si fière de cette définition de 1988, elle n'en aurait pas proposé une autre 6 ans plus tard Notamment, cette de 1994 est beaucoup plus stricte que celle de 1988, qui ne se base que sur le comportement substitué (comportement, au sens contrat). La définition usuelle courante parle de propriétés - dont, grosse différence, le comportement ne fait pas partie. Ces propriétés, je les ai cité dans un post précédent, je les liste à nouveau ici :

    * accès
    * pré- et post-conditions

    L'accès impose bien évidemment l'existence.

    LSP a effectivement des super-pouvoirs: grâce à ce principe, on sait si une classe peut dériver d'une autre. C'est quand même un point particulièrement important dans le domaine de l'architecture logicielle

    Outre ces points; il semblerait que certains d'entre vous continuent de mélanger "ce qu'il est possible de faire" et "ce qui doit être fait", en étant fortement influencé par les langages majeurs de notre génération. Les deux notions sont très différentes - il suffit d'installer eMule pour commencer à télécharger des films, donc c'est tout à fait possible. Est-ce que c'est ce qui doit être fait (au regard de la loi; vos opinions personnelles ont peu d'intérêt dans ce cas précis ).

    Ce qui doit être fait, c'est respecter LSP de manière correcte, y compris les notions d'accès, pré-condition et post-condition. Ce qui peut être fait, c'est passer outre certaines restrictions de LSP en se servant de certaines faiblesses des langages usuels.

    La pratique est plus permissive que la théorie, mais ça ne veut pas dire que la théorie accepte la pratique. Ce qui ne veut pas dire, en retour, que la pratique est condamnable : il y a des cas légitimes ou je peux souhaiter par exemple que toutes les fonctions de ma classe dérivée soit privées - Je peux l'instancier, mais je ne peux pas utiliser ses services. Je ne peux pas non plus l'étendre en la dérivant. J'impose une limitation technique, afin de contrôler au mieux mon design. C'est, en soi, une bonne chose. Ca reste une violation du LSP, mais (comme je l'ai dit auparavent) on conçoit des systèmes en s'appuyant sur des langages, et on utilise les possibilités de ces langages à notre avantage.

    Comme tout principe, comme toute règle, le LSP a une certaine souplesse. De la même manière qu'on peut violer une règle en motivant cette violation, LSP accepte d'être violé à condition que le résultat ait un intérêt fort. Il n'en reste pas moins violé, mais au moins, on sait pourquoi on le fait, et ce que ça nous apporte.

    Pour résumer : ce n'est pas parce que le pragmatisme s'éloigne un poil de la théorie que le pragmatisme a tord ou que la théorie a besoin d'être étendu. Comme le dit le célèbre adage, la différence entre la théorie et la pratique, c'est qu'en théorie, c'est la même chose.
    [FAQ des forums][FAQ Développement 2D, 3D et Jeux][Si vous ne savez pas ou vous en êtes...]
    Essayez d'écrire clairement (c'est à dire avec des mots français complets). SMS est votre ennemi.
    Evitez les arguments inutiles - DirectMachin vs. OpenTruc ou G++ vs. Café. C'est dépassé tout ça.
    Et si vous êtes sages, vous aurez peut être vous aussi la chance de passer à la télé. Ou pas.

    Ce site contient un forum d'entraide gratuit. Il ne s'use que si l'on ne s'en sert pas.

  20. #180
    Expert éminent sénior
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 612
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 612
    Points : 30 612
    Points
    30 612
    Par défaut
    Citation Envoyé par Emmanuel Deloget Voir le message
    Comme tout principe, comme toute règle, le LSP a une certaine souplesse. De la même manière qu'on peut violer une règle en motivant cette violation, LSP accepte d'être violé à condition que le résultat ait un intérêt fort. Il n'en reste pas moins violé, mais au moins, on sait pourquoi on le fait, et ce que ça nous apporte.
    Tout à fait, mais, à défaut d'avoir une justification cohérente et qui tient la route (non: la justification du "le langage le permet n'entre pas dans cette catégorie !!!), la violation ne peut absolument pas être envisagée.

    Que l'on envisage de contrevenir à LSP ou à n'importe quelle règle à un moment particulier, dans une situation tout à fait particulière et parce que l'on est en mesure de justifier pourquoi on le fait est cependant une chose très éloignée d'une discussion "générale" comme celle ci
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

Discussions similaires

  1. Réponses: 2
    Dernier message: 02/10/2008, 16h37
  2. Fonction appelant une fonction virtuelle pure
    Par oodini dans le forum C++
    Réponses: 12
    Dernier message: 19/09/2008, 08h24
  3. Une fonction virtuelle ne peut pas retourner un template!
    Par coyotte507 dans le forum Langage
    Réponses: 10
    Dernier message: 08/02/2008, 20h39
  4. Problème de visibilité d'une fonction
    Par hello2lu dans le forum VBA Access
    Réponses: 8
    Dernier message: 03/07/2007, 15h20
  5. Réponses: 2
    Dernier message: 05/03/2006, 19h29

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo