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 :

Héritage sans virtualité ?


Sujet :

Langage C++

  1. #41
    Expert éminent
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 644
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 644
    Par défaut
    Citation Envoyé par white_tentacle Voir le message
    subtype ≠ subclass. L’héritage n’est pas une condition nécessaire. C’est important de voir que, même si le papier parle aussi de la mise en œuvre du LSP dans les langages objets et donc de l’héritage, il ne s’y limite pas, étant à un niveau d’abstraction supérieur.
    Disons, surtout, que le principe est un principe de conception et que le langage n'est "qu'un outil" qui permet de le mettre en oeuvre, quel que soit la manière dont le langage l'apréhende

    Mais il est aussi vrai que Mme Liskov fait, explicitement, référence à des langages orientés objets et indique clairement que c'est quelque chose de difficile à envisager hors de ce contexte
    Après, c’est peut-être aussi moi qui vais un peu au-delà de l’énoncé initial. Mais ce n’est pas grave et je le maintiens , LSP ne saurait se limiter à l’héritage : un très bon exemple est les concepts c++.
    Attention, les concepts tels qu'ils étaient envisagés en C++ (car il n'ont pour finir pas été retenus dans la norme, malheureusement), sont une technique de programmation générique, et donc "hors scope" du LSP qui reste, malgré tout, un principe de conception OO.

    D'autant plus que les concepts C++ n'ont strictement rien à voir avec la substituabilité, mais permettent "juste" (enfin, ce n'est déjà pas si mal, hein ) de s'assurer que des classes sans rapport entre elles présente une interface représentant une capacité (ou un ensemble de capacités) exposée par le type d'objet concerné

    L'idée des concepts C++ est de d'accepter (ou non) de travailler avec des objets qui présentent des caractéristiques vérifiant le fait que l'objet est (par exemple) copiable, comparable par égalité, comparable par plus petit ou autre caractéristiques n'impliquant pas forcément une relation de subsituabilité
    Un cas classique est le stockage d’objets différents dans un même conteneur. Mais c’est quand même un mauvais exemple : chaque fois qu’on peut, il vaut mieux utiliser un variant qu’une hiérarchie pour faire ça
    C'est en effet un très mauvais exemple, car la solution la "moins mauvaise" consiste, en effet, à faire du "type ereasure" qui est, une fois de plus, hors scope du LSP, vu que la technique est... une technique de programmation générique
    (malheureusement, en java ou c#, on n’a pas vraiment le choix).
    A vrai dire, selon le coté d'où l'on se place, C# et java ont soit fait une très grosse erreur de conception dans le sens ou l'on peut difficielement estimer que "tout et n'importe quoi" puisse avoir une base commune dans le respect de LSP, soit poussé le raisonnement un peu trop loin et se sont trompés dans la "granularité" qu'ils ont utilisé lorsqu'ils ont réfléchi en terme d'héritage.

    Cependant, il faut leur laisser une chose : un garbage collector aurait été particulièrement difficile (pour ne pas dire impossible) à mettre en oeuvre s'ils n'avaient pas fait en sorte que toute classe hérite (de manière directe ou indirecte) d'une classe commune (Object)

    Note aussi que, pour autant que je m'en souvienne, java implémente maintenant le "generics" qui permettent (ou du moins sont sensé permettre, car je ne les connais pas assez pour me risquer à émettre un jugement quelconque dessus) de faire sensiblement la même chose

    Enfin, je reste vraiment très circonspect quant à l'idée de faire cohabiter une voiture et une banane dans une seule et même collection, et je ne l'accepterai vraiment que si je n'ai pas d'autre choix
    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

  2. #42
    Membre Expert
    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
    Par défaut
    Citation Envoyé par koala01 Voir le message
    Attention, les concepts tels qu'ils étaient envisagés en C++ (car il n'ont pour finir pas été retenus dans la norme, malheureusement), sont une technique de programmation générique, et donc "hors scope" du LSP qui reste, malgré tout, un principe de conception OO.

    D'autant plus que les concepts C++ n'ont strictement rien à voir avec la substituabilité, mais permettent "juste" (enfin, ce n'est déjà pas si mal, hein ) de s'assurer que des classes sans rapport entre elles présente une interface représentant une capacité (ou un ensemble de capacités) exposée par le type d'objet concerné
    La principale différence entre généricité et polymorphisme, c’est que le premier est statique tandis que le second est runtime, et donc les deux s’implémentent de manière différente. Mais dans les deux cas, il y a substitution.

    Mais si tu regardes bien comment fonctionnent les concepts, soit une classe générique G<C>, tu sais que tu peux utiliser G pour tout type compatible avec ton concept C. Et un type « compatible avec C », c’est un type qui vérifie à minima chacune des propriétés de C, ce qui ressemble quand même foutrement à l’énoncé du LSP . C’est vraiment la notion de « behavioral subtyping » qui est ici en action.

  3. #43
    Expert éminent
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 644
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 644
    Par défaut
    Citation Envoyé par white_tentacle Voir le message
    La principale différence entre généricité et polymorphisme, c’est que le premier est statique tandis que le second est runtime, et donc les deux s’implémentent de manière différente. Mais dans les deux cas, il y a substitution.

    Mais si tu regardes bien comment fonctionnent les concepts, soit une classe générique G<C>, tu sais que tu peux utiliser G pour tout type compatible avec ton concept C. Et un type « compatible avec C », c’est un type qui vérifie à minima chacune des propriétés de C, ce qui ressemble quand même foutrement à l’énoncé du LSP . C’est vraiment la notion de « behavioral subtyping » qui est ici en action.
    Je t'accorde volontiers que l'on peut parler de substitution, mais tu sembles oublier que l'approche du paradigme orienté objets est totalement différente de l'approche du paradigme générique...

    Pour rappel, le paradigme purement impératif va être essentiellement dirigé vers les données ("Data driven"), à savoir que l'on va penser purement et simplement en terme de données (même si elles peuvent être encapsulées).

    Le paradigme orienté objets va quant à lui s'intéresser non plus aux données, mais au comportement que l'on peut attendre d'un objet: les données dont un objet est composé ne sont plus que des détails d'implémentation permettant à l'objet de rendre le service que l'on en attend.

    Enfin, le paradigme générique va partir du principe que, si l'on ne sait pas encore quel sera le type de l'objet manipulé, on sait par contre parfaitement comment il sera manipulé.

    Tu as donc, effectivement, une certaine substituabilité dans le sens où tout type présentant un ensemble des propriétés attendues peut effectivement être utilisé avec ta fonction (ou ta classe) générique, mais cela ne veut absolument pas dire que tes types sont substituables aux termes du paradigme orienté objets.

    Je te rappelle que LSP dit que toute propriété valide pour un type T doit etre valide pour le type S tel si S est un sous type de T.

    Cela n'implique pas forcément, si T et V ont un ensemble de propriétés identiques, que T et V présentent d'office une quelconque relation de sous typage, même s'il est effectivement possible mais pas obligatoire qu'une telle relation puisse exister


    C'est la raison pour laquelle, bien que l'on puisse parler de « behavioral subtyping » avec le paradigme générique, il s'agit, ni plus ni moins, d'une considération "hors scope" par rapport au LSP

    Comprends bien que LSP est à appliquer quand on envisage de faire en sorte qu'un type S soit sous type de T, afin de s'assurer tout S puisse être sustitué partou où un T est attendu mais que du point de vue de la programmation générique, S n'a pas forcément besoin d'être sous type de T pour pouvoir être substitué : il "suffit" qu'il expose des propriétés similaires

    Je ne reviens décidément plus sur le terme, mais il ne faut pas croire que le fait que la présence de propriétés identiques implique forcément le respect de LSP, même si le respect de LSP implique forcément que les propriétés du type de base font partie des propriétés du sous type
    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

  4. #44
    Membre Expert

    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 : 35
    Localisation : France, Doubs (Franche Comté)

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

    Informations forums :
    Inscription : Août 2004
    Messages : 1 391
    Par défaut
    @white_tentacle: J'ai un peu de mal à voir le lien que tu vois entre LSP et concept. D'un point de vue mathématique le LSP définit une relation d'ordre sur l'ensemble des types. Un concept n'étant pas un type je ne vois pas comment il se retrouve ordonné dans cet ensemble ?

  5. #45
    Membre éprouvé
    Profil pro
    Inscrit en
    Novembre 2004
    Messages
    2 766
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Novembre 2004
    Messages : 2 766
    Par défaut
    Citation Envoyé par koala01 Voir le message
    Enfin, le paradigme générique va partir du principe que, si l'on ne sait pas encore quel sera le type de l'objet manipulé
    On peut toutefois, lors de la définition de templates, préciser que l'instanciation ne sera possible que pour certains types d'objets (voir les classes de traits introduites par C++11), notamment en indiquant une hiérarchie de types autorisée.

  6. #46
    Expert éminent
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 644
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 644
    Par défaut
    Citation Envoyé par oodini Voir le message
    On peut toutefois, lors de la définition de templates, préciser que l'instanciation ne sera possible que pour certains types d'objets (voir les classes de traits introduites par C++11), notamment en indiquant une hiérarchie de types autorisée.
    Tout à fait...

    Mais il faut comprendre que, dés que tu décides de travailler avec un pointeur ou une référence, tu peux, par définition oserais-je presque dire, travailler avec des hiérarchies d'objets polymorphes

    D'un autre coté, les classes de traits permettent juste de s'assurer que le type utilisé présentera effectivement "tout ce qu'il faut" pour remplir les conditions d'utilisation.

    Elle peuvent, en effet, forcer à l'utilisation de types particuliers et donc à l'utilisation d'objets polymorphes, mais il n'y a strictement aucune obligation quant au fait que les objets soient polymorphes ni qu'ils fassent partie d'une quelconque hiérarchie

    Intéresses toi peut etre au contenu des fichiers d'en-tête de la STL, et tu constatera par toi même que l'ensemble de cette partie de la bibliothèque standard ne fait strictement aucune présomption sur le type des données effectivement manipulées : La classe string (en fait, la classe basic_string, pour être précis) elle-même est faite pour pouvoir s'adapter à différent types de bytes et certaines classes (essentiellement les collections) poussent même le vice jusqu'à estimer que, non seulement elles ne savent pas quel sera l'objet manipulé, mais qu'elles ne savent même pas ni comment il est construit, ni comment il est détruit!!!


    Au passage... Les classes de traits ont peut etre été améliorées dans la nouvelle norme, mais elle faisaient déjà partie de la norme de 2003 (section 17.1.18, même si ca tient sur deux lignes)
    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. #47
    Membre Expert
    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
    Par défaut
    Citation Envoyé par Flob90 Voir le message
    @white_tentacle: J'ai un peu de mal à voir le lien que tu vois entre LSP et concept. D'un point de vue mathématique le LSP définit une relation d'ordre sur l'ensemble des types. Un concept n'étant pas un type je ne vois pas comment il se retrouve ordonné dans cet ensemble ?
    Un concept, c’est un ensemble de propriétés que peut/doit respecter un type. Personnellement, je vois ça un peu comme un type abstrait. Effectivement, il s’abstrait de toute hiérarchie « exprimée », car les templates et l’héritage sont indépendants. Néanmoins, la hiérarchie au sens LSP existe toujours : soit le type est compatible avec le concept, et il est « en dessous », soit ce n’est pas le cas, et il est à côté ou au-dessus.

    À noter, pour faire une analogie, qu’en Eiffel, où on a une généricité contrainte par les types, on recourt souvent à une classe abstraite pour exprimer cette contrainte. C’est la même idée, en un peu moins souple par contre, car ici la hiérarchie doit être explicite.

  8. #48
    Membre Expert

    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 : 35
    Localisation : France, Doubs (Franche Comté)

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

    Informations forums :
    Inscription : Août 2004
    Messages : 1 391
    Par défaut
    @white_tentacle: Pour moi :
    • Concept : Moyen d'exprimer explicitement un contrat, du moins en partie
    • LSP : Relation d'ordre "comportemental" des types

    A part le fait qu'il touche tout les deux aux comportements des types, je ne vois pas d'analogie .

    Définir un "lien" entre Concept et Type ne me gène pas, mais quand il est exprimé avec un outil lié aux liens entre les types, ca me gène un peu. Le lien entre les deux pour moins ca serait plutôt qu'un Concept est lié à un ensemble de type (ceux les réprésentant) (*).

    L'implémentation de quelque chose se rapprochant le plus des concepts, pour moi (et les langages que je connais, au moins un peu) c'est les classes de types d'Haskell .

    (*) Et en couplant ce lien mathématique entre Concept et type et le LSP, on pourrait exprimer formellement une idée de Concept orthogonaux comme un partionnement de l'ensemble des types maximaux au sens du LSP. Par contre l'intérêt pratique reste discutable ...

Discussions similaires

  1. [JMerise] Version 0.3.9.7 - Héritage sans contrainte
    Par aidefz dans le forum JFreesoft
    Réponses: 3
    Dernier message: 14/09/2015, 15h31
  2. Modéliser héritage sans exclusion
    Par Lystik dans le forum UML
    Réponses: 3
    Dernier message: 31/07/2013, 17h24
  3. Implémentation héritage sans relation cyclique
    Par Driss35 dans le forum Diagrammes de Classes
    Réponses: 6
    Dernier message: 03/08/2012, 19h50
  4. [modelisation] Héritage sans nouvelles spécifications
    Par poukill dans le forum Diagrammes de Classes
    Réponses: 8
    Dernier message: 21/06/2007, 14h15
  5. Réponses: 3
    Dernier message: 04/06/2007, 08h34

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