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

C++ Discussion :

[LSP] Comment représenter un carré à partir d'un rectangle ?


Sujet :

C++

  1. #1
    Membre éprouvé Avatar de Steph_ng8
    Homme Profil pro
    Doctorant en Informatique
    Inscrit en
    Septembre 2010
    Messages
    677
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 39
    Localisation : France

    Informations professionnelles :
    Activité : Doctorant en Informatique

    Informations forums :
    Inscription : Septembre 2010
    Messages : 677
    Points : 997
    Points
    997
    Par défaut [LSP] Comment représenter un carré à partir d'un rectangle ?
    Bonsoir.
    Je crois que le titre est suffisamment explicite pour ceux qui connaissent le principe de substitution de Liskov.
    Je dispose d'une classe, et certaines caractéristiques particulières sont suffisamment intéressantes pour former une nouvelle (sous-)classe.
    Comment faire cohabiter correctement ces deux classes, si possible en conservant d'une manière ou d'une autre le lien qui les unit, tout en respectant ce fameux principe ?

    Appelons A la classe de départ, et B la classe qui représente le « cas particulier ».
    Une solution consiste à en faire des classes sœurs.
    Cela me paraît un bon compromis, mais si vous avez d'autres idées, je suis preneur.
    Si vous pensez que c'est mauvais, je suis preneur aussi.

    Dans certains cas, je me retrouve dans une situation légèrement plus subtile.
    Si je pouvais le représenter pas des template, je ferai ainsi :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    template <unsigned int N, typename... Args> // length(Args) == N
    class A;
     
    typedef A<0> B;
    Comment puis-je faire cela proprement, si N et Args sont des données membres ?

    Pour information, dans mon projet les instances ne sont pas construites directement (via des fabriques, par exemple).
    Aucune instance générale ne peut donc être construite si elle était en fait particulière.

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

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 614
    Points : 30 626
    Points
    30 626
    Par défaut
    Salut,

    En deux mots, tu ne peux envisager de créer une sous classe que si l'ensemble des invariants, préconditions et postconditions satisfont à certaines règles

    Pour rappel :
    1. Les préconditions ne peuvent pas etre renforcées dans le sous type
    2. Les postconditions ne peuvent pas être allégée dans le sous type
    3. Les invariants du type de base doivent etre respectés dans le sous type.


    Si ce n'est pas le cas, tu peux envisager deux possibilités : soit tes deux classes sont soeurs (le meme parent, mais aucun lien d'héritage entre les deux), soit tu considère que le cas particulier n'est "qu'un état particulier" du cas de base.

    Il faut cependant être conscient que chacune de ces solutions présentera des avantages et des inconvénients:

    la première solution aura pour intérêt de permettre de gérer les invariants, pré et post conditions de manière optimale, mais l'inconvénient majeur de rendre la conversion de l'un en l'autre beaucoup plus difficile à cause de l'utilisation de deux types différents.

    La seconde solution permet de manipuler le cas particulier comme si c'était le cas de base, mais, les invariants et conditions n'étant pas obligatoirement respectées pour le cas particulier, tu devras envisager de tester l'état de ton objet "à tout bout de champs".

    Au final, on pourrait dire qu'il est important de savoir ce que tu attends de tes types, de manière à être en mesure d'évaluer l'intérêt effectif de ta décision...

    Si l'on reprend l'exemple du titre de ta question, nous pourrions dire que, si l'idée est de gérer le carré et le rectangle comme des éléments qui peuvent être tracés (aux cotés d'autres formes pouvant elles aussi être tracées), le fait d'envisager le carré comme étant simplement un état particulier du rectangle est tout à fait raisonnable.

    Si, par contre, ce qui t'importe, ce sont les caractéristiques géométriques des différentes formes, parce que tu les utilises essentiellement pour des calculs d'aires, de périmètres ou autres trucs du genre, il vaut mieux considérer le fait d'avoir deux types effectivement différents
    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

  3. #3
    Membre éprouvé Avatar de Steph_ng8
    Homme Profil pro
    Doctorant en Informatique
    Inscrit en
    Septembre 2010
    Messages
    677
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 39
    Localisation : France

    Informations professionnelles :
    Activité : Doctorant en Informatique

    Informations forums :
    Inscription : Septembre 2010
    Messages : 677
    Points : 997
    Points
    997
    Par défaut
    Bon, j'avais oublié que, dans mon cas, si conceptuellement un B peut être vu comme un A, le comportement d'un B est relativement différent de celui d'un A.
    Le mieux est d'en faire des classe sœurs.
    Et comme on ne cherche pas à convertir un B en A…

    Pour l'autre situation, c'est vraiment un cas particulier.
    Les invariants et les postconditions ne sont pas touchés.
    Pour les préconditions, on rajoute juste que N == 0, et Args == {} (les deux sont équivalents puisqu'un invariant de A est N == length(Args)).
    Ceci dit, dans l'application, il y a peu de chances que l'on utilise un B comme un A, et on ne créera jamais de A qui serait un B.
    Mais ça permet de réutiliser tout ce qui a été mis en place pour A.

    Bon, merci de m'avoir rappelé l'essentiel.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Réponses: 11
    Dernier message: 25/05/2006, 11h42
  2. Réponses: 2
    Dernier message: 25/03/2005, 09h23
  3. [Hook] Comment connaître la Form à partir d'un TPoint ?
    Par remixtech dans le forum API, COM et SDKs
    Réponses: 19
    Dernier message: 06/02/2005, 01h22
  4. Réponses: 3
    Dernier message: 08/01/2005, 10h01
  5. Comment créer un bitmap à partir d'un panel ?
    Par calou34 dans le forum Composants VCL
    Réponses: 3
    Dernier message: 19/08/2003, 15h06

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