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

Python Discussion :

Héritage multiple. Question d'architecture.


Sujet :

Python

  1. #1
    Membre régulier
    Profil pro
    Inscrit en
    Novembre 2008
    Messages
    99
    Détails du profil
    Informations personnelles :
    Âge : 46
    Localisation : France

    Informations forums :
    Inscription : Novembre 2008
    Messages : 99
    Points : 102
    Points
    102
    Par défaut Héritage multiple. Question d'architecture.
    Bonjour tout le monde,

    J'ai une petite question plutôt d'ordre architecture que code pure.

    Je vous explique mon dilemme. J'ai une classe de base - appelé originalement Base - dont j'ai fais dériver 2 classes - SubBase1 et SubBase2. Chacune de ces deux classes re-implémente une méthode appelé lock(). Jusque la rien d'affolant.
    J'ai ensuite eu besoin de spécialiser chacune de ces 2 méthodes lock() de la même façon.
    Ma première façon de faire a été de dériver chacune de mes 2 classe - SubBase1Spé et SubBase2Spé - et de redéfinir les 2 implémentations de lock(), sachant que chacune d'elle appelle la version de leur classe de base.
    La encore rien de bien méchant.

    Après implémentation de ces 2 nouvelles classes dérivées, je me suis rendu compte que le code de spécialisation était complètement dupliqué entre mes deux classes. Et pour éviter cette duplication de code j'ai donc créé une classe de spécialisation - appelé la encore très originalement Spe - dont j'ai fait hérité chacune de mes 2 classes SubBase1Spé et SubBase2Spé.

    Normalement la, vous êtes perdu, alors voila un petit diagramme de classe:
    Code Diagramme de classe : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
            Base
              |
       +------+-------+
       |              |
    SubBase1       SubBase2
       |              |
       |     Spé      |
       | +----+-----+ |
       | |          | |
    SubBase1Spé   SubBase2Spé

    Et en code:
    Code Et en python maintenant : 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
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
     
    class Base(object):
        ''' Classe de base '''
        def lock(self):
            print "Base::lock() method call."
            raise NotImplemented()
     
    class SubBase1(Base):
        ''' Classes derivee 1 '''
        def lock(self):
            print "SubBase1::lock() method call."
     
     
    class SubBase2(Base):
        ''' Classes derivee 2 '''
        def lock(self):
            print "SubBase2::lock() method call."
     
     
    class Spe(object):
        ''' Classe de specialisation '''
        def lock(self):
            print "Spe::lock() method call."
            return super(Spe, self).lock()
     
    class SubBase1Spe(Spe, SubBase1):
        ''' Classe specialisee 1 '''
     
    class SubBase2Spe(Spe, SubBase2):
        ''' Classe specialisee 1 '''
     
    print "Creation de SubBase1Spe"
    SubBase1Spe().lock()
    print
     
    print "Creation de SubBase2Spe"
    SubBase2Spe().lock()
    print

    Et voila, ca marche. Mais en relisant mon code, je me rend compte que la méthode lock() de Spe se retrouve à appeler une méthode d'une classe au même niveau qu'elle dans la hiérarchie... et ca c'est.... moche, en étant particulièrement gentil avec moi-même :-)
    ex: Spe::lock() appelle SubBase1::lock() ou SubBase2::lock().

    Je ne sais pas trop comment faire quelque chose d'élégant avec ca. Je suis en train de me dire que le code dupliqué avait au moins la bonne idée d'être une bonne approche de l'héritage de tout cela. Quelqu'un aurait-il une idée sur une bonne façon de faire les choses ?

    Merci d'avance.

  2. #2
    Membre habitué Avatar de KINENVEU
    Profil pro
    Inscrit en
    Mai 2007
    Messages
    184
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2007
    Messages : 184
    Points : 131
    Points
    131
    Par défaut
    ca fait ce que tu voulais,
    mais perso, je ne comprends pas pourquoi ca marche.
    pourquoi tu ne prends pas une erreur a l'appel : "super(Spe, self).lock()" ?
    car la classe mere de "Spe" est "object" et n'a pas de methode "lock".

    il y a surement quelque chose qui m'echappe ...

  3. #3
    Membre régulier
    Profil pro
    Inscrit en
    Novembre 2008
    Messages
    99
    Détails du profil
    Informations personnelles :
    Âge : 46
    Localisation : France

    Informations forums :
    Inscription : Novembre 2008
    Messages : 99
    Points : 102
    Points
    102
    Par défaut
    En fait cela marche parce que super a un comportement qui n'est pas exactement celui que l'on s'attend à voir.
    Contrairement à ce que j'avais pensé la première fois que j'ai lu la description, super n'appelle pas forcement la méthode de la classe mère. La sémantique de cette fonction est d'appeler la méthode suivante avec l'algorithme de résolution de nom - donc la suivante avec leur méthode dites en diamant.

    Dans mon cas, si l'on considère que self est de type SubBase2Spé, l'ordre dans lequel doivent être appelé les méthodes est : SubBase2Spé, Spé, SubBase1, Base et finalement object.
    En suivant cet ordre, Si dans Spé::lock() on appel la méthode suivante, on tombe bien sur SubBase1::lock(), ce qui est conforme au comportement du code.

    Mais en terme d'architecture OOP, y'a vraiment un truc dérangeant qu'on ne peut faire - à ma connaissance - qu'avec Python qui est d'appeler une méthode qui peut être plus 'haute' dans la hiérarchie de classe que la méthode courante. Et ca c'est vraiment étrange comme comportement.

    En ce qui concerne l'utilisation de super il y a un article assez intéressant qui met en garde contre l'utilisation abusive de cette fonction ICI.

  4. #4
    Membre confirmé
    Avatar de vincent.mbg
    Homme Profil pro
    Développeur Python
    Inscrit en
    Décembre 2007
    Messages
    327
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Développeur Python

    Informations forums :
    Inscription : Décembre 2007
    Messages : 327
    Points : 618
    Points
    618
    Par défaut
    Après implémentation de ces 2 nouvelles classes dérivées, je me suis rendu compte que le code de spécialisation était complètement dupliqué entre mes deux classes.
    Je n'ai pas bien saisi le problème.

    Sans la classe Spe, la Classe SubBase1Spe hérite de la méthode SubBase1::lock() et la classe SubBase2Spe hérite de la méthode SubBase2::lock().

    Cherchait tu un autre comportement à ce moment Là ?
    Mon guide pour apprendre Tkinter - N'oubliez pas de consulter les FAQ Python ou de visiter mon blog

  5. #5
    Membre régulier
    Profil pro
    Inscrit en
    Novembre 2008
    Messages
    99
    Détails du profil
    Informations personnelles :
    Âge : 46
    Localisation : France

    Informations forums :
    Inscription : Novembre 2008
    Messages : 99
    Points : 102
    Points
    102
    Par défaut
    Oui, je cherchais un comportement différent de celui-là car j'avais besoin d'un bout de code de spécialisation dans les méthodes SubBase1Spe::lock() et SubBase2Spe::lock()

    Au final SubBase1Spe::lock() appelait SubBase1::lock() et SubBase2Spe::lock() appelait SubBase2::lock().
    Mais les codes de ces deux fonctions SubBase*Spe::lock() étaient strictement les mêmes, hormis la ligne d'appel à la méthode parente. C'est cette duplication de code qui m'a motivé à changer ma hiérarchie de classe pour créer la classe Spe.

    Mon soucis c'est qu'en créant cette nouvelle classe Spe j'ai introduit une belle verrue dans mon code (l'appelle par une classe d'une méthode d'une classe "sœur" dans la hiérarchie de classe) et que je ne sais pas trop comment m'en sortir élégamment.
    J'en suis a me demander si Spe ne serait tout simplement pas un bon candidat à être non pas une classe de laquelle on hérite, mais plutôt une méta classe de spécialisation. Je ne suis juste pas très sur de moi car je ne maitrise pas vraiment la sémantique des méta-classes et leurs rôle exact.

  6. #6
    Membre confirmé
    Avatar de vincent.mbg
    Homme Profil pro
    Développeur Python
    Inscrit en
    Décembre 2007
    Messages
    327
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Développeur Python

    Informations forums :
    Inscription : Décembre 2007
    Messages : 327
    Points : 618
    Points
    618
    Par défaut
    Les métaclasses sont des outils permettant au développeur de créer des classes sous un certain format. une métaclasse peut par exemple obliger le développeur à créer la méthode __str__ pour une classe qu'il souhaite développer.

    il y a une fonction appelé staticmethode(). Je sais pas si sa peut te venir en aide.
    Mon guide pour apprendre Tkinter - N'oubliez pas de consulter les FAQ Python ou de visiter mon blog

  7. #7
    Membre régulier
    Profil pro
    Inscrit en
    Novembre 2008
    Messages
    99
    Détails du profil
    Informations personnelles :
    Âge : 46
    Localisation : France

    Informations forums :
    Inscription : Novembre 2008
    Messages : 99
    Points : 102
    Points
    102
    Par défaut
    Merci pour l'info, je suis en train de regarder ca de plus près.

    De mon coté, je lis un article assez intéressant que j'ai trouvé sur le site d'IBM qui traite des metaclasses en python, justement.
    Si ca intéresse des gens, c'est ICI que ca se passe.

Discussions similaires

  1. [2.x] Héritage ? : question d'architecture
    Par Linwe dans le forum Symfony
    Réponses: 2
    Dernier message: 26/12/2011, 23h58
  2. question d'héritage "multiple"
    Par splinternabs dans le forum ALM
    Réponses: 1
    Dernier message: 23/12/2011, 20h57
  3. Question sur l'héritage multiple
    Par paparasta dans le forum C++
    Réponses: 14
    Dernier message: 13/08/2010, 21h14
  4. question d'héritage multiple
    Par lao.patrick dans le forum C#
    Réponses: 2
    Dernier message: 02/05/2009, 11h52
  5. Questions sur l'héritage multiple
    Par beegees dans le forum C++
    Réponses: 12
    Dernier message: 31/03/2008, 17h01

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