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

VB.NET Discussion :

Héritage et Polymorphisme


Sujet :

VB.NET

  1. #1
    Membre émérite Avatar de mactwist69
    Homme Profil pro
    Développement VB.NET
    Inscrit en
    Janvier 2007
    Messages
    1 707
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 39
    Localisation : France, Saône et Loire (Bourgogne)

    Informations professionnelles :
    Activité : Développement VB.NET
    Secteur : Industrie

    Informations forums :
    Inscription : Janvier 2007
    Messages : 1 707
    Points : 2 528
    Points
    2 528
    Par défaut Héritage et Polymorphisme
    Bonjour collègue travailleurs de l'été !

    J'ai la mission de développer une bibliothèque de classe toute neuve, répondant à tous nos besoins, et j'ai carte blanche !

    J'ai fais donc des recherches pour essayer de faire quelque chose de très propre et j'ai quelques petites questions pratiques sur le polymorphisme et l'héritage :

    - est il possible d'avoir dans la classe mère une procédure commune A (exclusif a la classe mère), fasse appel à une procédure B, dont le contenu serait vide dans la classe mère (et à MustOverride), du coup elle serait obligatoirement implémenté dans les classe filles. Ma question est, est ce qu'avec le mécanisme de polymorphisme, lorsque A appel B, la classe mère, va chercher B dans la classe fille correspondante ?

    - Pourquoi on ne peut pas mettre le constructeur en MustOverride ? Moi j'aimerai que lorsqu'un développeur va créer une nouvelle classe fille, on l'oblige à créer son constructeur...
    L'avenir appartient à ceux... dont les ouvriers se lèvent tôt. (Coluche)

  2. #2
    Membre chevronné
    Avatar de Sehnsucht
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Octobre 2008
    Messages
    847
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France, Lot et Garonne (Aquitaine)

    Informations professionnelles :
    Activité : Développeur .NET

    Informations forums :
    Inscription : Octobre 2008
    Messages : 847
    Points : 2 209
    Points
    2 209
    Par défaut
    Ça n'aurait aucun sens d'avoir un constructeur en MustOverride, en effet ce mot clef sert à dire que l'appel est résolu en fonction du type concret de l'objet plutôt que du type de la variable que l'on manipule ; or dans le cas d'un constructeur on précise le type concret que l'on souhaite utiliser donc on sait déjà où va "partir" l'appel.
    Après rien ne t'empêche dans ta classe de base de définir un constructeur paramétré, ainsi les classes en héritant devront forcément au moins définir un constructeur (étant donné qu'aucun constructeur par défaut n'est accessible dans la classe parent)

    Pour ce qui est d'utiliser une méthode dans la classe de base qui appelle une procédure définie comme MustOverride (et donc la classe est en MustInherit), à l'utilisation ce sera bien dépendant du type concret, comme expliqué plus haut (et donc ça appellera bien la version de la classe fille). Attention toutefois, si jamais la classe fille redéfinit l'autre méthode (celle que tu as nommée A) en utilisant Shadows ou Overloads [ou sans rien mettre au prix d'un warning] et que tu utilises cette méthode A, là les choses vont changer, ça dépendra du type de la variable utilisées pour l'appel

    Moralité si tu veux être sûr que le polymorphisme s'applique, il faudra bien veiller à manipuler ta hierarchie en tant qu'instances concrètes stockées sous forme de base.

    Ci-joint un exemple de code vite fait, pour résumer :
    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
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    Sub Main()
        Dim simple As New DerivedSimple
        Dim overload As New DerivedOverloads
        Dim shadow As New DerivedShadows
     
        Console.WriteLine("Calling using ""real type""")
        simple.A()
        overload.A()
        shadow.A()
     
        Console.WriteLine()
        Console.WriteLine("Calling using ""base type""")
     
        ' array of derived typed as base
        Dim bases As Base() = {simple, overload, shadow}
        Array.ForEach(bases, Sub(b) b.A())
    End Sub
     
    MustInherit Class Base
     
        Sub A()
            Console.WriteLine("Inside Base.A()")
            B()
        End Sub
     
        Protected MustOverride Sub B()
     
    End Class
     
    Class DerivedSimple
        Inherits Base
     
        Protected Overrides Sub B()
            Console.WriteLine("Inside DerivedSimple.B()")
        End Sub
    End Class
     
    Class DerivedOverloads
        Inherits Base
     
        Overloads Sub A()
            Console.WriteLine("Inside DerivedOverloads.A()")
            Console.WriteLine("No I'm not going to call B()")
        End Sub
     
        Protected Overrides Sub B()
            Console.WriteLine("Inside DerivedOverloads.B()")
        End Sub
    End Class
     
    Class DerivedShadows
        Inherits Base
     
        Shadows Sub A()
            Console.WriteLine("Inside DerivedShadows.A()")
            Console.WriteLine("No I'm not going to call B()")
        End Sub
     
        Protected Overrides Sub B()
            Console.WriteLine("Inside DerivedShadows.B()")
        End Sub
    End Class
     
    ' output:
    ' Calling using "real type"
    ' Inside Base.A()
    ' Inside DerivedSimple.B()
    ' Inside DerivedOverloads.A()
    ' No I'm not going to call B()
    ' Inside DerivedShadows.A()
    ' No I'm not going to call B()
     
    ' Calling using "base type"
    ' Inside Base.A()
    ' Inside DerivedSimple.B()
    ' Inside Base.A()
    ' Inside DerivedOverloads.B()
    ' Inside Base.A()
    ' Inside DerivedShadows.B()
    Nous sommes tous plus ou moins geek : ce qui est inutile nous est parfaitement indispensable ( © Celira )
    À quelle heure dormez-vous ?
    Censément, quelqu'un de sensé est censé s'exprimer sensément.

  3. #3
    Membre émérite Avatar de mactwist69
    Homme Profil pro
    Développement VB.NET
    Inscrit en
    Janvier 2007
    Messages
    1 707
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 39
    Localisation : France, Saône et Loire (Bourgogne)

    Informations professionnelles :
    Activité : Développement VB.NET
    Secteur : Industrie

    Informations forums :
    Inscription : Janvier 2007
    Messages : 1 707
    Points : 2 528
    Points
    2 528
    Par défaut
    Merci déjà de la réponse rapide !! Qui plus est, très pertinente !

    Citation Envoyé par Sehnsucht Voir le message
    Ça n'aurait aucun sens d'avoir un constructeur en MustOverride, en effet ce mot clef sert à dire que l'appel est résolu en fonction du type concret de l'objet plutôt que du type de la variable que l'on manipule ; or dans le cas d'un constructeur on précise le type concret que l'on souhaite utiliser donc on sait déjà où va "partir" l'appel.
    -> C'est pas faux ! En fait c'était juste pour faire une contrainte aux développeurs de classe dérivées.

    Citation Envoyé par Sehnsucht Voir le message
    Après rien ne t'empêche dans ta classe de base de définir un constructeur paramétré, ainsi les classes en héritant devront forcément au moins définir un constructeur (étant donné qu'aucun constructeur par défaut n'est accessible dans la classe parent)
    -> C'est pas bête, mieux en fait même !

    Citation Envoyé par Sehnsucht Voir le message
    Pour ce qui est d'utiliser une méthode dans la classe de base qui appelle une procédure définie comme MustOverride (et donc la classe est en MustInherit), à l'utilisation ce sera bien dépendant du type concret, comme expliqué plus haut (et donc ça appellera bien la version de la classe fille).
    -> C'est exactement ce à quoi je pensais : Faire A dans la classe de base, ainsi les développeurs n'auront pas à effectuer dans chaque classe dérivée les différents contrôles de contraintes communes... Mais par contre les laisser développer la partie spécifique au type dérivée.


    Citation Envoyé par Sehnsucht Voir le message
    Attention toutefois, si jamais la classe fille redéfinit l'autre méthode (celle que tu as nommée A) en utilisant Shadows ou Overloads [ou sans rien mettre au prix d'un warning] et que tu utilises cette méthode A, là les choses vont changer, ça dépendra du type de la variable utilisées pour l'appel
    -> Je vais essayer de pas du tout toucher à ces fonctionnalités pour garder les choses assez simples. Du coup j'interdirai même la redéfinition de A dans la classe de base, et j'obligerai la redéfinition de B. Et c'est plus simple pour tout le monde...

    Merci des réponses, c'est parfait !
    L'avenir appartient à ceux... dont les ouvriers se lèvent tôt. (Coluche)

  4. #4
    Membre chevronné
    Avatar de Sehnsucht
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Octobre 2008
    Messages
    847
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France, Lot et Garonne (Aquitaine)

    Informations professionnelles :
    Activité : Développeur .NET

    Informations forums :
    Inscription : Octobre 2008
    Messages : 847
    Points : 2 209
    Points
    2 209
    Par défaut
    Citation Envoyé par mactwist69 Voir le message
    -> C'est pas bête, mieux en fait même !
    Par contre de cette manière tu "obliges" juste la présence d'un constructeur, t'as aucun contrôle sur la signature. Comprendre c'est pas parce que tu spécifies Sub New(s As String) que les héritiers doivent respecter la même signature ils doivent juste avoir un constructeur qui en premier lieu appelle le constructeur parent

    Citation Envoyé par mactwist69 Voir le message
    -> Je vais essayer de pas du tout toucher à ces fonctionnalités pour garder les choses assez simples. Du coup j'interdirai même la redéfinition de A dans la classe de base, et j'obligerai la redéfinition de B. Et c'est plus simple pour tout le monde...
    Pas sûr de bien comprendre, mais si tu comptes trouver un moyen d'empêcher aux héritiers d'utiliser Shadows/Overloads je te souhaite bonne chance, parce qu'à ma connaissance il n'en existe pas (à part justement en passant par le constructeur qui n'est pas "Shadowable/Overloadable")
    Nous sommes tous plus ou moins geek : ce qui est inutile nous est parfaitement indispensable ( © Celira )
    À quelle heure dormez-vous ?
    Censément, quelqu'un de sensé est censé s'exprimer sensément.

  5. #5
    Membre émérite Avatar de mactwist69
    Homme Profil pro
    Développement VB.NET
    Inscrit en
    Janvier 2007
    Messages
    1 707
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 39
    Localisation : France, Saône et Loire (Bourgogne)

    Informations professionnelles :
    Activité : Développement VB.NET
    Secteur : Industrie

    Informations forums :
    Inscription : Janvier 2007
    Messages : 1 707
    Points : 2 528
    Points
    2 528
    Par défaut
    Citation Envoyé par Sehnsucht Voir le message
    Par contre de cette manière tu "obliges" juste la présence d'un constructeur, t'as aucun contrôle sur la signature. Comprendre c'est pas parce que tu spécifies Sub New(s As String) que les héritiers doivent respecter la même signature
    ->Got it

    Citation Envoyé par Sehnsucht Voir le message
    ils doivent juste avoir un constructeur qui en premier lieu appelle le constructeur parent
    -> Je ne m'étais pas posé la question, mais effectivement, ça tombe sous le sens. J'imagine qu'un MyBase.New() fait l'affaire.

    Citation Envoyé par Sehnsucht Voir le message
    si tu comptes trouver un moyen d'empêcher aux héritiers d'utiliser Shadows/Overloads
    -> Nan, c'est juste moi qui me mets des limites. Je n'utiliserai pas Shadow pour pas compliquer le programme. Si déjà tout le reste va bien et est bien conçu, il ne devrait pas y avoir de problème.
    L'avenir appartient à ceux... dont les ouvriers se lèvent tôt. (Coluche)

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

Discussions similaires

  1. héritage et polymorphisme
    Par julien.metais dans le forum Hibernate
    Réponses: 3
    Dernier message: 17/05/2009, 09h58
  2. Réponses: 10
    Dernier message: 17/07/2008, 20h01
  3. héritage et polymorphisme
    Par davdou dans le forum JSF
    Réponses: 2
    Dernier message: 23/11/2007, 09h51
  4. [C#] Information sur héritage et polymorphisme
    Par LE NEINDRE dans le forum C#
    Réponses: 21
    Dernier message: 14/06/2007, 11h00
  5. Réponses: 19
    Dernier message: 05/06/2007, 08h13

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