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 :

Heritage et surcharge : comment faire ?


Sujet :

VB.NET

  1. #1
    Membre éprouvé Avatar de electroremy
    Homme Profil pro
    Ingénieur sécurité
    Inscrit en
    Juin 2007
    Messages
    934
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Doubs (Franche Comté)

    Informations professionnelles :
    Activité : Ingénieur sécurité
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2007
    Messages : 934
    Points : 1 274
    Points
    1 274
    Par défaut Heritage et surcharge : comment faire ?
    Heritage et surcharge : comment faire ?

    J’ai une classe de base Usinage et plusieurs classes dérivées UPercage, UPercageF, …

    Je souhaite définir dans chaque classe dérivée une procédure « ImporterFPD » ayant chacune différents paramètres ; j’y suis arrivé mais la façon dont je m’y prends ne me plait pas :

    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
    Public MustInherit Class Usinage
        Protected X As Double
        Protected Y As Double
        ...
        ...
        Public Overridable Sub ImporterFPD(posX As Double, posY As Double, tailleD As Double)
        End Sub
        Public Overridable Sub ImporterFPD(posX As Double, posY As Double, tailleD As Double, tailleDF As Double, FaceAV As Boolean)
        End Sub
        ...
    End Class
     
     
    Public Class UPercage : Inherits Usinage
        Protected Diam As Double
        ...
        ...
        Public Overrides Sub ImporterFPD(posX As Double, posY As Double, tailleD As Double)
            X = posX
            Y = posY
            Diam = tailleD
        End Sub
    End Class
     
     
    Public Class UPercageF : Inherits Usinage
        Protected Diam As Double
        Protected DiamF As Double
        Protected FaceAvant As Boolean
        ...
        ...
        Public Overrides Sub ImporterFPD(posX As Double, posY As Double, tailleD As Double, tailleDF As Double, FaceAV As Boolean)
            X = posX
            Y = posY
            Diam = tailleD
            DiamF = tailleDF
            FaceAvant = FaceAV
        End Sub
    End Class
    Le soucis c’est que lorsque je tape le code, par exemple :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
            Dim usi As Usinage
            usi = New UPercage
            Call usi.ImporterFPD(50, 60, 3)
     
            usi = New UPercageF
            Call usi.ImporterFPD(50, 60, 3, 4, True)
            Call usi.ImporterFPD(50, 60, 3) 'Cette ligne n'est pas logique
    Il m’autorise à appeler une version de ImporterFPD() qui n’ pas de sens (la dernière ligne de mon exemple)

    En fait au départ je voulais faire ça mais ça ne fonctionne pas :

    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
    Public MustInherit Class Usinage
        Protected X As Double
        Protected Y As Double
        ...
        ...
    End Class
     
     
    Public Class UPercage : Inherits Usinage
        Protected Diam As Double
        ...
        ...
        Public Sub ImporterFPD(posX As Double, posY As Double, tailleD As Double)
            X = posX
            Y = posY
            Diam = tailleD
        End Sub
    End Class
     
     
    Public Class UPercageF : Inherits Usinage
        Protected Diam As Double
        Protected DiamF As Double
        Protected FaceAvant As Boolean
        ...
        ...
        Public Sub ImporterFPD(posX As Double, posY As Double, tailleD As Double, tailleDF As Double, FaceAV As Boolean)
            X = posX
            Y = posY
            Diam = tailleD
            DiamF = tailleDF
            FaceAvant = FaceAV
        End Sub
    End Class
    Comment dois-je m’y prendre ?

    J’ai examiné la documentation VB sur les mots clefs Shadows, Overloads, Overrides,Overridable, MustOverrides, … et fait différents essais mais sans succès.
    Quand deux personnes échangent un euro, chacun repart avec un euro.
    Quand deux personnes échangent une idée, chacun repart avec deux idées.

  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
    Bonsoir,

    Il y a comme un souci de design
    Si tu définis tes deux versions dans Usinage, cela signifie que TOUS les Usinage (aussi bien UPercage, UPercageF ou tout autre future classe dérivée) peuvent les utiliser.
    Si cela ne doit pas être le cas alors elles ne doivent pas êtres définies à cet endroit.

    De plus, étant donné que l'utilisation qui en est faite est d'initialiser les membres de la classe, il ne serait pas plus judicieux que ce soit des constructeurs.
    Également, il semblerait (par l'utilisation et aussi son nom) que UPercageF devrait dériver de UPercage et non de Usinage

    En gros, si je résume le tout, voilà (potentiellement) ce que j'aurais fait au vu des informations:
    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
    Public MustInherit Class Usinage
     
        Protected X, Y As Double
     
        Public Sub New(ByVal posX As Double, ByVal poxY As Double)
            X = posX
            Y = poxY
        End Sub
     
    End Class
     
    Public Class UPercage
        Inherits Usinage
     
        Protected Diam As Double
     
        Public Sub New(ByVal posX As Double, ByVal posY As Double, ByVal tailleD As Double)
            MyBase.New(posX, posY)
            Diam = tailleD
        End Sub
     
    End Class
     
    Public Class UPercageF
        Inherits UPercage
     
        Protected DiamF As Double
        Protected FaceAvant As Boolean
     
        Public Sub New(ByVal posX As Double, ByVal posY As Double, ByVal tailleD As Double, ByVal tailleDF As Double, ByVal faceAV As Boolean)
            MyBase.New(posX, posY, tailleD)
            DiamF = tailleDF
            FaceAvant = faceAV
        End Sub
     
    End Class
    Cordialement !
    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 éprouvé Avatar de electroremy
    Homme Profil pro
    Ingénieur sécurité
    Inscrit en
    Juin 2007
    Messages
    934
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Doubs (Franche Comté)

    Informations professionnelles :
    Activité : Ingénieur sécurité
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2007
    Messages : 934
    Points : 1 274
    Points
    1 274
    Par défaut
    merci

    mais ces fonctions ImporterFPD ne doivent pas êtres des constructeurs

    en fait j'ai simplifié le code avant de le mettre sur le forum pour eviter de vous noyer sous quelquechose de trop long

    Citation Envoyé par Sehnsucht Voir le message
    Bonsoir,

    Il y a comme un souci de design
    Si tu définis tes deux versions dans Usinage, cela signifie que TOUS les Usinage (aussi bien UPercage, UPercageF ou tout autre future classe dérivée) peuvent les utiliser.
    Si cela ne doit pas être le cas alors elles ne doivent pas êtres définies à cet endroit.

    De plus, étant donné que l'utilisation qui en est faite est d'initialiser les membres de la classe, il ne serait pas plus judicieux que ce soit des constructeurs.
    Également, il semblerait (par l'utilisation et aussi son nom) que UPercageF devrait dériver de UPercage et non de Usinage

    En gros, si je résume le tout, voilà (potentiellement) ce que j'aurais fait au vu des informations:
    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
    Public MustInherit Class Usinage
     
        Protected X, Y As Double
     
        Public Sub New(ByVal posX As Double, ByVal poxY As Double)
            X = posX
            Y = poxY
        End Sub
     
    End Class
     
    Public Class UPercage
        Inherits Usinage
     
        Protected Diam As Double
     
        Public Sub New(ByVal posX As Double, ByVal posY As Double, ByVal tailleD As Double)
            MyBase.New(posX, posY)
            Diam = tailleD
        End Sub
     
    End Class
     
    Public Class UPercageF
        Inherits UPercage
     
        Protected DiamF As Double
        Protected FaceAvant As Boolean
     
        Public Sub New(ByVal posX As Double, ByVal posY As Double, ByVal tailleD As Double, ByVal tailleDF As Double, ByVal faceAV As Boolean)
            MyBase.New(posX, posY, tailleD)
            DiamF = tailleDF
            FaceAvant = faceAV
        End Sub
     
    End Class
    Cordialement !
    Quand deux personnes échangent un euro, chacun repart avec un euro.
    Quand deux personnes échangent une idée, chacun repart avec deux idées.

  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
    Ça ne change pas grand chose à la logique de ce que j'ai dit.
    Tu peux faire une méthode ImporterFPD dans Usinage qui attend posX et posY.
    Dans UPercage tu la redéfinis (à l'aide de Overloads) pour rajouter tailleD (et en la faisant appeler la méthode de sa classe parente.
    Et dans UPercageF idem avec tailleDF et faceAV.

    Ainsi une variable de type Usinage n'aura accès qu'à la surcharge simple.
    Une variable de type UPercage aura accès aux deux (parce qu'un UPercage EST UN Usinage et par conséquent tout ce qu'on peut faire sur un Usinage on doit pouvoir le faire avec un UPercage).
    Une variable de type UPercageF aura accès aux trois (parce qu'un UPercageF EST UN UPercage qui est un Usinage [si on respecte la hiérarchie exposée dans mon post précédent] et par conséquent tout ce qu'on peut faire sur un Usinage ou un UPercage on doit pouvoir le faire avec un UPercageF).

    Si tu veux faire autre chose que le comportement décrit là, tu ne t'orientes pas dans la bonne direction en voulant utiliser la surcharge et/ou le polymorphisme.

    Cordialement !
    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 éprouvé Avatar de electroremy
    Homme Profil pro
    Ingénieur sécurité
    Inscrit en
    Juin 2007
    Messages
    934
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Doubs (Franche Comté)

    Informations professionnelles :
    Activité : Ingénieur sécurité
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2007
    Messages : 934
    Points : 1 274
    Points
    1 274
    Par défaut RE
    Bonsoir,

    j'avais déjà tenté ce que tu m'a suggéré mais sans succès

    voici une nouvelle tentative, elle aussi infructueuse :

    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
    Public MustInherit Class Usinage
        Protected X As Double
        Protected Y As Double
        '...
        Public Sub ImporterFPD(ByVal posX As Double, ByVal posY As Double)
            X = posX
            Y = posY
        End Sub
    End Class
     
     
    Public Class UPercage : Inherits Usinage
        Protected Diam As Double
        '...
        Public Overloads Sub ImporterFPD(ByVal posX As Double, ByVal posY As Double, ByVal tailleD As Double)
            Call MyBase.ImporterFPD(posX, posY)
            Diam = tailleD
        End Sub
    End Class
     
     
    Public Class URectangle : Inherits Usinage
        Protected TX As Double
        Protected TY As Double
        '...
        Public Overloads Sub ImporterFPD(ByVal posX As Double, ByVal posY As Double, ByVal tailleX As Double, ByVal tailleY As Double)
            Call MyBase.ImporterFPD(posX, posY)
            TX = tailleX
            TY = tailleY
        End Sub
    End Class
    mais ça ne fonctionne pas;

    lorsque j'essaye de faire ça :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
            Dim usi As Usinage
            usi = New URectangle
            usi.ImporterFPD(100, 110, 50, 40)
            usi = New UPercage
            usi.ImporterFPD(100, 110, 3)
    VB m'envoie bouler : "Arguments trop nombreux pour ImporterFDP(posX as Double, posY as Double"

    VB ne reconnais que .ImporterFPD(posX as Double, posY as Double) et ne tiens pas compte de mes fonctions surchargées dans les classes dérivées

    VB ne veux pas non plus que je remplace Overloads par Overrides.

    PS : cet exemple est volontairement simple; en réalité, ImporterFPD effectura des calculs de convertion de donnée différents pour chaque classe dérivée, ce n'est pas un constructeur tout bête.

    En d'autres termes, ma question est "comment redéfinir une fonction dans une classe dérivée mais avec un prototype différent de celle de la classe de base en VB ?"

    Ce que je ne comprends pas non plus c'est pourquoi une fonction déclarée PUBLIC dans une classe dérivée est innaccessible si elle n'est pas déclarée dans la classe de base ? La surcharge ou l'occultation serait de fait obligatoire ?

    merci, A+

    PS : ce code là fonctionne :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
            Dim usi As URectangle
            usi = New URectangle
            usi.ImporterFPD(100, 110, 50, 40)
            Dim usi2 As UPercage
            usi2 = New UPercage
            usi2.ImporterFPD(100, 110, 3)
    mais abandonner le polymorphisme... aucun interêt
    Quand deux personnes échangent un euro, chacun repart avec un euro.
    Quand deux personnes échangent une idée, chacun repart avec deux idées.

  6. #6
    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 electroremy Voir le message
    VB ne reconnais que .ImporterFPD(posX as Double, posY as Double) et ne tiens pas compte de mes fonctions surchargées dans les classes dérivées

    En d'autres termes, ma question est "comment redéfinir une fonction dans une classe dérivée mais avec un prototype différent de celle de la classe de base en VB ?"
    Réponse courte: tu ne peux pas!
    C'est exactement ce que j'ai expliqué dans mes posts précédent.
    Pour illustrer je vais prendre un autre exemple:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    Public MustInherit Class Vehicule
        Public MustOverride Sub Avancer(dx, dy)
    End Class
    Je définis une classe abstraite Vehicule avec une méthode abstraite Avancer (en me disant "après tout tous les véhicules peuvent faire ça, seul le comment change")
    Puis (plus tard) quelqu'un (pas forcément moi) définit ceci:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    Public Class Avion
        Inherits Vehicule
        Public Overrides Sub Avancer(dx, dy, dz)
    End Class
    En se disant un avion peut aussi se déplacer sur le 3ème axe [Note: on met de côté le fait que ceci ne compilera pas]

    là on est dans ta situation (juste les MustOverride/Overrides en plus mais ça change pas grand chose)
    et là ce que tu veux faire c'est:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    Dim v As Vehicule = New Avion()
    v.Avancer(x, y, z)
    sauf que ça peut marcher que si c'est un avion ça, et le compilo lui ne le sait pas ; il a un vehicule et c'est tout.

    Redéfinir une fonction c'est dire "moi j'ai une autre manière de faire la même chose" exemple:
    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
    Public MustInherit Class Forme
        Public MustOverride ReadOnly Property Aire As Double
    End Class
     
    Public Class Cercle
        Inherits Forme
        Private rayon As Double
     
        Public Overrides ReadOnly Property Aire As Double
            Get
                Return Math.PI * rayon * rayon
            End Get
        End Propery
    End Class
     
    Public Class Rectangle
        Inherits Forme
        Private largeur, longueur As Double
     
        Public Overrides ReadOnly Property Aire As Double
            Get
                Return largeur * longueur
            End Get
        End Property
    End Class
    '...
    Dim forme As Forme = New Rectangle(7.0, 8.0) 'On suppose le constructeur écrit
    Dim aire As Double = forme.Aire 'aire vaudra 56.0
    Là c'est clair toutes les formes ont une aire, c'est juste la méthode de calcul qui change.

    Autre exemple (pour illustrer le cas nombre d'argument différent), prends la méthode ToString() qui existe pour tout objet (justement parce qu'elle est définie surchargeable dans Object dont "tout" dérive),
    on a aussi d'autres type qui ont d'autres versions (exemple Integer.ToString(format As String))
    mais on ne peut pas écrire ceci:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    Dim nombre As Object = 42
    nombre.ToString("N0") 'ne fonctionne pas
    Tout simplement parce que nombre est ici un Object (ou si tu préfères un Integer considéré du point de vue de son "parent" Object) et ce type ne possède pas de méthode avec cette signature.

    Citation Envoyé par electroremy Voir le message
    Ce que je ne comprends pas non plus c'est pourquoi une fonction déclarée PUBLIC dans une classe dérivée est innaccessible si elle n'est pas déclarée dans la classe de base ? La surcharge ou l'occultation serait de fait obligatoire ?
    Pourquoi le serait-elle c'est le contraire qui est vrai, une membre Public (ou Protected) dans la classe de Base est visible dans la classe Dérivée parce q'une instance de Dérivé EST UNE instance de Base
    • un Avion EST UN Vehicule, mais un Vehicule n'est pas forcément un Avion.
    • un Cercle EST UNE Forme, mais une Forme n'est pas forcément un Cercle.
    • un UPercage EST UN Usinage, mais un Usinage n'est pas forcément un UPercage.

    Moralité tout ce qui appartient à Base appartient à Dérivé, mais ce qui appartient à Dérivé n'appartient pas forcément à Base.

    C'est la même chose que l'exemple avec nombre:
    Si tu utilises UPercage "directement" tu auras accès à tout ce que "connait" UPercage (dont la partie héritée de Usinage).
    Mais toi tu utilises UPercage en tant que Usinage donc tu n'as accès qu'à ce que "connait" Usinage (c'est à dire ses choses à lui et s'il y en a les choses dont il hérité [exemple ToString() qui lui vient de Object ])

    Désolé, c'est un peu plus long que ce que je pensais au départ mais cette explication/vulgarisation me semblait nécessaire.

    Cordialement !

    Edit (Réponse au PS): ce que tu fais ce n'est pas du polymorphisme, comment tu fait pour savoir quels paramètres passer à "usi" sans savoir ce qu'il "contient" actuellement ?
    le vrai polymorphisme c'est "on s'en fiche de ce que c'est réellement, je lui donne ce qu'il attend, il fait sa tambouille et me donne (s'il y a) le résultat"
    comme avec forme, peu importe laquelle j'obtiens son aire.

    Ou autre exemple, la classe Control, définit beaucoup de choses reprises (potentiellement) différemment par ses enfants
    GetStyle dit juste j'ai un Controle, je veux son style, le comment c'est chaque enfant qui le gère en fonction de son cas personnel.
    Et celui qui veut faire un GetStyle spécial ? il peut, mais pour pouvoir l'utiliser faudra savoir qu'on s'adresse à lui (sinon comment je saurais qu'il l'a ?)
    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.

  7. #7
    Membre éprouvé Avatar de electroremy
    Homme Profil pro
    Ingénieur sécurité
    Inscrit en
    Juin 2007
    Messages
    934
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Doubs (Franche Comté)

    Informations professionnelles :
    Activité : Ingénieur sécurité
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2007
    Messages : 934
    Points : 1 274
    Points
    1 274
    Par défaut
    Bonsoir,

    En fait au moment du codage, avant l'execution, VB ne peut pas déterminer quelle classe dérivée est stockée dans une variable du type de la classe de base, donc determiner quelle surcharge appeller.

    J'avais vraiement du mal à voir la différence entre ce que je veux faire, et les exemples donnés dans les § "IV. La surcharge de méthode" et "V. La redéfinition de méthodes" de ce tutorial : http://mbenzeghiba.developpez.com/tu...heritagevbnet/

    A+

    PS : sinon... ce code la fonctionne... mais je pense que c'est crade

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    Dim usi
    usi = New URectangle
    usi.ImporterFPD(100, 110, 50, 40)
    usi = New UPercage
    usi.ImporterFPD(100, 110, 3)
    Quand deux personnes échangent un euro, chacun repart avec un euro.
    Quand deux personnes échangent une idée, chacun repart avec deux idées.

  8. #8
    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 electroremy Voir le message
    VB ne peut pas déterminer quelle classe dérivée est stockée dans une variable du type de la classe de base, donc determiner quelle surcharge appeller.
    En fait c'est pas vraiment qu'il peut ou ne peut pas, c'est qu'il ne cherche pas à savoir.

    Tu mets un UPercage dans une variable de type Usinage, ça veut donc bien dire que tu ne t'intéresses qu'à la partie Usinage et ce qu'elle permet de faire.

    C'est comme [encore une comparaison pourrie ] si tu avais un t'as d'animaux et dedans tu cherches à savoir combien il y a de mammifères. Tu t'en fiches de savoir si c'est des ours ou des baleines.

    Si je résume:
    • la surcharge c'est quand [quelqu'un] une classe peut faire quelque chose de plusieurs façon
      Code : Sélectionner tout - Visualiser dans une fenêtre à part
      1
      2
      3
      4
      5
      6
      7
      8
      9
      Class Foo
          Public Function Distance(x1, y1, x2, y2) As Double
              Return Math.Sqrt(Math.Pow(x1 - x2, 2) + Math.Pow(y1 - y2, 2))
          End Function
          Public Function Distance(point1, point2) As Double
              Return Distance(point1.X, point1.Y, point2.X, point2.Y)
              ' ici j'ai appelé l'autre version, mais ce n'est pas (toujours) une obligation
          End Function
      End Class
    • la redéfinition c'est quand un dérivé doit faire la même chose qu'un base mais d'une façon différente ou quand base définit un comportait abstrait et le dérivé décrit ce comportement pour son cas concret.
      Par exemple l'aire d'une forme c'est abstrait (ça dépend quelle forme)
      Autre exemple, avec mes mammifères de tout à l'heure, si je voulais faire le total des pattes et si je voulais le total des pattes de tous les animaux ? (y'a pas que les mammifères qui ont des pattes)
      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
      MustInherit Class Animal
          Public MustOverride ReadOnly Property Pattes As Integer
      End Class
      MustInherit Class Mammifere
          Inherits Animal
          ' pas besoin de redéclarer Pattes ici, Mammifere l'hérite d'Animal
          ' et elle ne sait pas comment le définir
      End Class
      Class Ours
          Inherits Mammifere
          Public Overrides ReadOnly Property Pattes As Integer
              Get
                  Return 4
              End Get
          End Property
      End Class
      Class Baleine
          Inherits Mammifere
          Public Overrides ReadOnly Property Pattes As Integer
              Get
                  Return 0
              End Get
          End Property
      End Class
      Class Tortue 'Pas un mammifère mais quand même un animal
          Inherits Animal
          Public Overrides ReadOnly Property Pattes As Integer
              Get
                  Return 4
              End Get
          End Property
      End Class
      Me suffit juste de grouper les animaux ensemble, idem avec les mammifères puis de parcourir ça en utilisant la propriété Pattes qui renverra ce qu'il faut et je pourrais faire mes comptages de pattes.

      [Note: les surcharges d'une redéfinition doivent utiliser le mot clef Overloads dans la classe dérivée]
    • l'occultation c'est la redéfinition d'un membre parent qui n'a pas été déclaré redéfinissable.
      (Celui là je connais moins, je m'en sers jamais, vouloir redéfinir un truc que son auteur a pas voulu redéfinissable, ça sent (sauf cas particuliers) l'erreur de "conception" et l'occultation a pas mal de défauts/contraintes, voir ton tuto)


    Cordialement !
    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.

  9. #9
    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
    Bon, double-post mais comme ça risque d'être un peu long, je préfère.

    J'ai réfléchi à ton souci, une solution que j'entrevois, serait d'utiliser une sorte de "pattern factory", à savoir une autre classe construit tes instances.

    tout d'abord, voilà ma hiérarchie de classe exemple:
    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
    Public MustInherit Class Usinage
        Private X, Y As Double
     
        Friend Sub New(ByVal posX As Double, ByVal posY As Double)
            X = posX
            Y = posY
        End Sub
     
        Public ReadOnly Property Nom As String
            Get
                Return Me.GetType.Name
            End Get
        End Property
     
        Public Overridable Function CalculerCout(Optional ByVal quantite As Integer = 1) As Double
            Return (X + Y) * quantite
        End Function
    End Class
     
    Public Class UPercage
        Inherits Usinage
        Private Diam As Double
     
        Friend Sub New(ByVal posX As Double, ByVal posY As Double, ByVal tailleD As Double)
            MyBase.New(posX, posY)
            Diam = tailleD
        End Sub
     
        Public Overrides Function CalculerCout(Optional ByVal quantite As Integer = 1) As Double
            Dim coutBase As Double = MyBase.CalculerCout(quantite)
            Return coutBase + Diam * quantite
        End Function
    End Class
     
    Public Class UPercageF
        Inherits UPercage
        Private DiamF As Double
        Private FaceAvant As Boolean
     
        Friend Sub New(ByVal posX As Double, ByVal posY As Double, ByVal tailleD As Double, ByVal tailleDF As Double, ByVal faceAV As Boolean)
            MyBase.New(posX, posY, tailleD)
            DiamF = tailleDF
            FaceAvant = faceAV
        End Sub
     
        Public Overrides Function CalculerCout(Optional ByVal quantite As Integer = 1) As Double
            Dim coutBase As Double = MyBase.CalculerCout(quantite)
            Return coutBase + (DiamF + If(FaceAvant, 10, 0)) * quantite
        End Function
    End Class
     
    Public Class URectangle
        Inherits Usinage
        Protected TX, TY As Double
     
        Friend Sub New(ByVal posX As Double, ByVal posY As Double, ByVal tailleX As Double, ByVal tailleY As Double)
            MyBase.New(posX, posY)
            TX = tailleX
            TY = tailleY
        End Sub
     
        Public Overrides Function CalculerCout(Optional ByVal quantite As Integer = 1) As Double
            Dim coutBase As Double = MyBase.CalculerCout(quantite)
            Return coutBase + (TX + TY) * quantite
        End Function
    End Class
    On a donc Usinage dont dérivent UPercage et URectangle et UPercageF qui dérive de UPercage (donc aussi de Usinage indirectement).
    J'ai mis les membres (X, Diam, tailleY, etc.) privés pour montrer qu'avec la redéfinition si on appelle la méthode parent c'est elle qui gère ses membres propres.
    J'ai défini une propriété (Nom) non-redéfinissable dans la classe de base car toute la hierarchie le fera de la même façon.
    Par contre, le calcul du cout est différent donc ça c'est redéfinissable [j'ai pris une regle simple, la somme des valeurs des membres multipliée par la quantité (avec le bool FaceAvant qui vaut 10 s'il est sur True sinon 0)]
    Pour calculer un cout, on récupère le cout du parent et on y ajoute le cout de ses membres propres.
    J'ai aussi défini des constructeurs déclaré Friend, cela signifie que seul ce qui est dans le même assembly peut y accéder, et comme ça on ne peut accéder aux membres privés depuis l'extérieur.

    Ensuite voilà la fabrique:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    Module FabriqueUsinage
        Public Function ImporterFPD(ByVal posX As Double, ByVal posY As Double, ByVal tailleD As Double) As Usinage
            Return New UPercage(posX, posY, tailleD)
        End Function
     
        Public Function ImporterFPD(ByVal posx As Double, ByVal posY As Double, ByVal tailleD As Double, ByVal tailleDF As Double, ByVal faceAvant As Boolean) As Usinage
            Return New UPercageF(posx, posY, tailleD, tailleDF, faceAvant)
        End Function
     
        Public Function ImporterFPD(ByVal posX As Double, ByVal posY As Double, ByVal tailleX As Double, ByVal tailleY As Double) As Usinage
            Return New URectangle(posX, posY, tailleX, tailleY)
        End Function
    End Module
    J'ai utilisé un module parce que sémantiquement, c'est l'équivalent d'une classe statique, c'est à dire que tout dedans est statique (Shared en VB.Net) par défaut et qu'on ne peut créer d'instance de cette classe/module elle sert juste à faire des opérations, ici créer des Usinage.
    Et pour ce faire j'ai mes surcharges de méthode ImporterFPD avec différentes signature qui renvoient toutes des Usinage mais "du bon" type" si je peux le dire ainsi (et on voit que j'utilise le constructeur définit tout à l'heure, la raison du Friend)

    Maintenant un peu Main de test pour montrer l'utilisation:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    Dim usinages As Usinage() = {
        FabriqueUsinage.ImporterFPD(1, 2, 3, 4),
        FabriqueUsinage.ImporterFPD(1, 2, 3),
        FabriqueUsinage.ImporterFPD(1, 2, 3, 4, True)
    }
     
    For Each usi As Usinage In usinages
        Console.WriteLine("{0}, Cout = {1}", usi.Nom, usi.CalculerCout)
    Next
    je crée d'abord un tableau de Usinage que je remplis en utilisant la Fabrique (parce que si le main n'est pas dans le même assembly c'est la seule manière de faire, comme je n'ai plus accès au constructeur)
    J'ai donc dans usinages un URectangle, un UPercage et un UPercageF
    Enfin, je parcours mon tableau, en affichant pour chaque son nom suivi de son cout (pour une quantité de 1 vu que c'est la valeur par défaut de l'argument)
    Grâce à la redéfinition même si "visuellement" je n'ai que des Usinage la bonne méthode sera appelée pour chaque qu'il soit URectangle etc.

    et j'obtiens donc comme affichage:
    Code Console : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    URectangle, Cout = 10
    UPercage, Cout = 6
    UPercageF, Cout = 20
    Si je détaille le calcul (comme j'ai pris les mêmes argument pour construire chaque) ça donne:
    Code Console : 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
    Usinage.X = 1
    Usinage.Y = 2
    UPercage.Diam = URectangle.TX 3
    UPercageF.DiamF = URectangle.TY = 4
    UPercage.FaceAV = True (donc 10)
     
    donc
    Cout(Usinage) = Usinage.X + Usinage.Y = 1 + 2 = 3
     
    Cout(URectangle) = Cout(Usinage) + URectangle.TX + URectangle.TY
    Cout(URectangle) = 3             + 3             + 4             = 10
     
    Cout(UPercage) = Cout(Usinage) + UPercage.Diam = 3 + 3 = 6
     
    Cout(UPercageF) = Cout(UPercage) + UPercageF.DiamF + UPercageF.FaceAV
    Cout(UPercageF) = 6              + 4               + 10               = 20

    Voilà, je ne suis pas sûr que ce soit la meilleure solution, il y aura surement des choses à adapter si tu l'utilises, mais ça te donne un exemple plus concret (appliqué à ta problématique) et ça met en oeuvre aussi bien la surcharge que la redéfinition (pas d'occultation, je l'ai dit je ne m'en sers pour ainsi dire jamais).

    Cordialement !
    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.

Discussions similaires

  1. Comment faire - Interface, surcharge
    Par arouche dans le forum C#
    Réponses: 3
    Dernier message: 30/01/2007, 18h41
  2. [C#] Heritage multiple -> comment faire autrement
    Par schnourf dans le forum Windows Forms
    Réponses: 14
    Dernier message: 03/10/2006, 15h14
  3. Réponses: 8
    Dernier message: 18/09/2002, 03h20
  4. Comment faire pour mettre l'ecran en veille ?
    Par March' dans le forum MFC
    Réponses: 6
    Dernier message: 29/08/2002, 14h25
  5. Comment faire pour créer un bitmap
    Par GliGli dans le forum C++Builder
    Réponses: 2
    Dernier message: 24/04/2002, 15h41

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