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

Dotnet Discussion :

Interfaces d'objets - Comment programmer ?


Sujet :

Dotnet

  1. #1
    Membre confirmé
    Profil pro
    Inscrit en
    Décembre 2005
    Messages
    77
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2005
    Messages : 77
    Par défaut Interfaces d'objets - Comment programmer ?
    Bonjour,

    J'ai un petit souci sur une notion en programmation.

    Exemple : je veux créer une classe boulon qui comprend la classe vis et la classe écrou. Pour que la vis s'assemble avec l'écrou, il faut qu'ils aient (toujours par exemple) le même diamètre.

    Quand je code, je peux définir toutes les propriétés et méthodes pour la vis.
    Idem pour l'écrou. Je définis donc des classes indépendantes.

    Question : comment puis-je faire pour que la propriété diamètre, soit la même pour les deux classes ? Est-il possible de définir une propriété commune ?

    Je peux bidouiller bien sûr, en déplaçant la propriété commune vers la classe boulon mais cette méthode devient franchement pénible dans des cas plus complexes, avec des dizaines d'objets inbriqués.

    Une idée ?

    Merci

  2. #2
    Expert confirmé
    Avatar de StringBuilder
    Homme Profil pro
    Chef de projets
    Inscrit en
    Février 2010
    Messages
    4 197
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Chef de projets
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2010
    Messages : 4 197
    Billets dans le blog
    1
    Par défaut
    Dans un premier temps, tu peux faire une assertion lorsque tu déclare la vis et l'écrou au niveau du boulon.

    Ensuite, tu peux mettre une seconde assertion dans le set {} du diamètre de la vis et de l'écrou lorsqu'ils sont membre d'un boulon.

    Un truc du genre :
    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
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
     
    using System;
     
    namespace TestBoulon
    {
        public class CVis
        {
            private int _diametre;
            private CBoulon _boulon;
     
            public CVis(int diametre)
            {
                _diametre = diametre;
            }
     
            public int Diametre
            {
                get
                {
                    return _diametre;
                }
                set
                {
                    if (_boulon != null && _boulon.Ecrou != null && value != _boulon.Ecrou.Diametre)
                    {
                        throw new Exception("Nan, pas possible.");
                    }
                    _diametre = value;
                }
            }
     
            public void SetBoulon(CBoulon boulon)
            {
                if (_boulon.Ecrou != null && _diametre != boulon.Ecrou.Diametre)
                {
                    throw new Exception("Nan, pas possible.");
                }
                _boulon = boulon;
            }
        }
     
        public class CEcrou
        {
            private int _diametre;
            private CBoulon _boulon;
     
            public CEcrou(int diametre)
            {
                _diametre = diametre;
            }
     
            public int Diametre
            {
                get
                {
                    return _diametre;
                }
                set
                {
                    if (_boulon != null && _boulon.Vis != null && value != _boulon.Vis.Diametre)
                    {
                        throw new Exception("Nan, pas possible.");
                    }
                    _diametre = value;
                }
            }
     
            public void SetBoulon(CBoulon boulon)
            {
                if (_boulon.Vis != null && _diametre != boulon.Vis.Diametre)
                {
                    throw new Exception("Nan, pas possible.");
                }
                _boulon = boulon;
            }
        }
     
        public class CBoulon
        {
            public CVis Vis;
            public CEcrou Ecrou;
     
            public CBoulon(CVis vis, CEcrou ecrou)
            {
                if (vis.Diametre != ecrou.Diametre)
                {
                    throw new Exception("Nan, pas possible.");
                }
                Vis = vis;
                Ecrou = ecrou;
     
                Vis.SetBoulon(this);
                Ecrou.SetBoulon(this);
            }
     
            public int Diametre
            {
                get
                {
                    return Vis.Diametre;
                }
            }
        }
    }
    Le truc chiant, c'est quand tu vas vouloir changer le diamètre du boulon une fois la vis et l'écrou déclarés... Si tu veux pouvoir le faire, il va falloir complexifier un peu.

  3. #3
    Membre confirmé
    Profil pro
    Inscrit en
    Décembre 2005
    Messages
    77
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2005
    Messages : 77
    Par défaut
    Merci pour ta réponse rapide et précise.

    Je comprends bien que c'est faisable mais pas simple.

    Imaginons maintenant que je travaille avec un moteur entier qui peut mécaniquement se définir comme un assemblage d'objets (de pièces).

    Ces nombreux objets, j'aimerais les modéliser séparément ! Puis les assembler dans une grosse classe moteur.

    Et là, avec la méthode qui vient d'être proposée, je vais avoir une architecture globale ingérable. Il me faut une autre solution (certains objets peuvent avoir des dizaines de propriétés communes).

    Globalement, je m'étonne que la notion d'interface (propriétés comunes) ne soit pas plus simple en langage objet (je ne suis pas informaticien de formation).

  4. #4
    Membre Expert Avatar de DonQuiche
    Inscrit en
    Septembre 2010
    Messages
    2 741
    Détails du profil
    Informations forums :
    Inscription : Septembre 2010
    Messages : 2 741
    Par défaut
    Bonjour.

    Il est possible de définir une propriété commune via les interfaces. Par exemple IHasDiameter avec une propriété Diameter. Ecrou, Vis et Boulon peuvent alors déclarer cette interface et la propriété correspondante.

    Cela dit, j'ai l'impression que tu fais fausse route quelque part. Pourrais-tu nous donner un exemple d'usage de la propriété diamètre ? Des scénarios où elle sera utilisée en nous précisant qui la consultera ? Et plus généralement qui parcourera ta hiérarchie d'objets et comment ?

    S'il s'agit par exemple de faire des tests mécaniques, j'ai dans l'idée que ce n'est pas la bonne voie.

  5. #5
    Membre confirmé
    Profil pro
    Inscrit en
    Décembre 2005
    Messages
    77
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2005
    Messages : 77
    Par défaut
    Je fais sans doute fausse route, je ne sais pas.
    Je cherche juste à bien programmer tout ça.

    L'usage de mes applications est le calcul mécanique.
    La problématique peut concerner tout autre type d'activité.
    Cela peut aussi être les classes racine + tronc + feuille formant un arbre.

    Le but, dans mon cas est le calcul.
    Sur l'exemple boulon, le diamètre permet avec une autre propriété matériau de définir une méthode charge maximale supportée (je simplifie).

    Je passe mes classes d'une application à l'autre suivant les besoins.
    Je n'ai pas envie de les réécrire à chaque fois.

    Si je fais fausse route, quel serait le bon chemin ?

  6. #6
    Membre Expert Avatar de DonQuiche
    Inscrit en
    Septembre 2010
    Messages
    2 741
    Détails du profil
    Informations forums :
    Inscription : Septembre 2010
    Messages : 2 741
    Par défaut
    En fait, il existe en développement logiciel un motif de conception (Information Expert) qui préconise de confier une tâche à la classe ayant la plus grande part des informations nécessaires. En l’occurrence, ce principe nous conseille donc de ne pas chercher à faire un grand superviseur qui se chargerait de tous les calculs mais plutôt de laisser chaque pièce effectuer les calculs la concernant.

    Dans ce cas de figure, vis, écrou et boulon n'ont pas besoin de clamer au monde entier qu'ils sont de ceux qui un diamètre. Boulon sait qu'il a une vis et un écrou et, puisqu'il connaît le type de ces deux pièces, il sait spontanément qu'ils ont tous deux un diamètre sans qu'une interface soit nécessaire. Ici, boulon a donc ce qu'il faut pour interagir avec eux et effectuer les calculs à son propre sujet en interagissant avec les méthodes fournies par vis et écrou.

    Par exemple (implémentation naïve), pour le calcul, tous les pièces mécaniques pourraient hériter d'une même classe de base ayant une fonction abstraite GetTorseur(Vector position). Chaque classe se chargerait d'implémenter ce code. L'appelant n'aurait pas besoin de savoir si c'est un chou ou un boulon, s'il a un diamètre ou un poids, etc...

    Comme en réalité il y aura vraisemblablement plusieurs types de calculs, selon le type d'action mécanique à évaluer, c'est plutôt en fonction des méthodes que chacun devra exposer pour ces calculs que l'on créer des interfaces ad hoc ou de nouvelles classes de base. Par exemple, tu pourrais avoir une interface IFluidVolume commune aux gaz et liquides qui exposerait les méthodes et propriétés nécessaires au traitement d'un fluide. C'est plus logique que d'essayer de faire une batterie d'interfaces IHasDensity, IHasCompressibility, etc. Dans ce cas, un objet Pompe serait rattachée à deux objets du type IFluidVolume.

  7. #7
    Expert confirmé
    Avatar de StringBuilder
    Homme Profil pro
    Chef de projets
    Inscrit en
    Février 2010
    Messages
    4 197
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Chef de projets
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2010
    Messages : 4 197
    Billets dans le blog
    1
    Par défaut
    Hmmm, j'avais cru comprendre que la question n'était pas de savoir si Ecrou et Vis avaient ou non un diamètre, mais de vérifier que dans un même Boulon, Ecrou et Vis avaient forcément le même diamètre (c'est à dire la même valeur).

    => Une Vis et un Ecrou ne peuvent pas avoir de diamètre qui évolue dans le temps : c'est donc une propriété qui est propre à la vis à et l'écrou. Si la Vis ou l'Ecrou se retrouvent séparés, ils doivent conserver la valeur de leur diamètre.

    => Si on tente de mettre une Vis et un Ecrou dans un Boulon, alors que la Vis et l'Ecrou n'ont pas le même diamètre, on ne doit pas le permettre.

    C'est en tout cas dans ce sens que j'ai répondu avec mon exemple.

    La classe Boulon ne peut avoir seule la propriété diamètre, et elle n'est pas la seule à pouvoir faire le contrôle de la compatibilité du diamètre : on peut tout à fait imaginer passer dans un écrou une tige filleté qui ne soit pas une Vis, et glisser une Vis dans un pas de vis qui n'est pas un écrou. Il faut donc que Ecrou et Vis soient chacun capable de vérifier la compatibilité avec l' (les) objet(s) au(x)quel il est lié.

  8. #8
    Membre confirmé
    Profil pro
    Inscrit en
    Décembre 2005
    Messages
    77
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2005
    Messages : 77
    Par défaut
    Merci pour vos contributions.
    Je reprends le fil.

    Donquiche :
    Pour le calcul, tous les pièces mécaniques pourraient hériter d'une même classe de base ayant une fonction abstraite GetTorseur(Vector position)
    Pas dans ce cas, chaque pièce se vérifie avec ses propres méthodes de calcul. Les classes sont vraiment indépendantes, pas d'héritage.

    StringBuilder :
    la question n'était pas de savoir si Ecrou et Vis avaient ou non un diamètre, mais de vérifier que dans un même Boulon, Ecrou et Vis avaient forcément le même diamètre
    Le test est bien sûr important mais, ce qui m'embête le plus c'est la notion de propriétés communes (ce que j'appelle les interfaces des pièces).

    Il faudrait que je puisse faire en sorte que la propriété diamètre de vis pointe vers la propriété diamètre de l'écrou, voire vers celle du boulon (boulon = vis + ecrou).

    Sinon, je fais quelque-chose comme ça :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    Dim boulon1 As New Class_boulon
    boulon1.ecrou.diametre = 12
    boulon1.vis.diametre = 12
    Mais ça devient très pénible à écrire quand on a des mécanismes plus complexes avec de nombreuses variables partagées (ex : matériau).

    Il me manque, la notion de propriété partagée en fait. Ou bien c'est une fausse route : il faut faire autrement.

    Idée : je déclare aussi diamètre dans class_boulon et je gère un évènement sur cette propriété qui modifiera diamètre dans ecrou et vis ?...

  9. #9
    Membre expérimenté
    Homme Profil pro
    Inscrit en
    Février 2003
    Messages
    2 194
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : Belgique

    Informations forums :
    Inscription : Février 2003
    Messages : 2 194
    Par défaut
    Tu passes vis et écrou en private

    Tu ajoutes une propriété Diametre à ta classe Boulon qui elle set les 2 diamètres

    Quand on veut ajouter une vis/écrou à ton boulon tu vérifies que celui-ci est compatible

    euh oui si suis ton idée

  10. #10
    Membre Expert Avatar de DonQuiche
    Inscrit en
    Septembre 2010
    Messages
    2 741
    Détails du profil
    Informations forums :
    Inscription : Septembre 2010
    Messages : 2 741
    Par défaut
    Citation Envoyé par yann_DZ Voir le message
    Pas dans ce cas, chaque pièce se vérifie avec ses propres méthodes de calcul. Les classes sont vraiment indépendantes, pas d'héritage.
    Ok.

    Maintenant, pour revenir au diamètre, est-il vraiment nécessaire que le graphe soit cohérent à tout instant ? Est-ce qu'on ne pourrait pas se contenter de valider son état à certains moments ? D'une part ça éviterait des constructions lourdingues impliquant des événements dans tous les sens ou des propriétés partagées ou encore je ne sais quoi d'autre. Je trouve la solution où aucune propriété n'est corrélée et où l'état est validé ultérieurement plus élégante.

    Qui plus est je trouve peu élégant et contre-intuitif (du point de vue du code) l'idée que modifier le diamètre de vis altère aussi le diamètre de écrou et boulon. C'est en revanche acceptable sur l'UI parce qu'il y a immédiatement ou presque un feedback visuel (au pire l'utilisateur se rend compte après avoir modifié vis et en allant modifier écrou que ça a été fait automatiquement). Rien à redire à non plus sur une propriété de Boulon qui modifierait automatiquement les valeurs des enfants.

    Maintenant, j'imagine que tu es venu poser cette question parce que nombre de pièces ont des propriétés qui sont liées entre parent-enfants ? Et que tu souhaites mettre en place, pour l'UI principalement (et pour une éventuelle validation avant le calcul) un système commun de mise à jour rapide en cascade des valeurs ? Si oui je me tournerais plutôt vers un système automatisé basé sur la décoration par des attributs et l'usage de la réflexion.

  11. #11
    Expert confirmé
    Avatar de StringBuilder
    Homme Profil pro
    Chef de projets
    Inscrit en
    Février 2010
    Messages
    4 197
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Chef de projets
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2010
    Messages : 4 197
    Billets dans le blog
    1
    Par défaut
    Et pourquoi pas mettre le diamètre dans une class abstraite dont héritent Boulon, Vis et Ecrou ?

    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
    80
    81
    82
    83
    84
    85
    86
    87
    88
     
     
        abstract class BoulonBase
        {
            protected BoulonBase parent = null;
     
            private int _diametre = 0;
     
            public int Diametre
            {
                get
                {
                    if (parent != null && parent.Diametre > 0)
                    {
                        return parent.Diametre;
                    }
                    return _diametre;
                }
                set
                {
                    if (parent != null)
                    {
                        throw new Exception("Ouais mais en fait, non.");
                    }
                    _diametre = value;
                }
            }
        }
     
        class Boulon : BoulonBase
        {
            public Vis _v;
            public Ecrou _e;
     
            public Boulon(Vis v, Ecrou e)
            {
                v.SetParent(this);
                _v = v;
     
                e.SetParent(this);
                _e = e;
            }
        }
     
        class Vis : BoulonBase
        {
            public Vis(int diametre)
            {
                Diametre = diametre;
            }
     
            public void SetParent(BoulonBase b)
            {
                if (!(b is Boulon))
                {
                    b.
                    throw new Exception("Une vis ne peut avoir comme parent qu'un Boulon");
                }
                if (b.Diametre > 0 && b.Diametre != Diametre)
                {
                    throw new Exception("Nan, c'est pas compatible.");
                }
                b.Diametre = Diametre;
                parent = b;
            }
        }
     
        class Ecrou : BoulonBase
        {
            public Ecrou(int diametre)
            {
                Diametre = diametre;
            }
     
            public void SetParent(BoulonBase b)
            {
                if (!(b is Boulon))
                {
                    throw new Exception("Un écrou ne peut avoir comme parent qu'un Boulon");
                }
                if (b.Diametre != Diametre)
                {
                    throw new Exception("Nan, c'est pas compatible.");
                }
     
                parent = b;
            }
        }
    Ainsi, que tu modifies la vis, l'écrou ou le boulon, tu modifie le diamètre de tout le monde.

  12. #12
    Membre Expert Avatar de DonQuiche
    Inscrit en
    Septembre 2010
    Messages
    2 741
    Détails du profil
    Informations forums :
    Inscription : Septembre 2010
    Messages : 2 741
    Par défaut
    @StringBuilder
    L'ennui, c'est que j'imagine qu'une vis peut être utilisée pour autre chose qu'un boulon. Et dans ce cas la contrainte disparaît ou est peut remplacée par une autre équivalente (vis + pas de vis = ?). Autre cas : comment est organisé le graphe pour une plaque avec deux pas de vis ?

  13. #13
    Membre confirmé
    Profil pro
    Inscrit en
    Décembre 2005
    Messages
    77
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2005
    Messages : 77
    Par défaut
    @BenoitM
    Tu ajoutes une propriété Diametre à ta classe Boulon qui elle set les 2 diamètres
    OK, ça va éviter de gérer un évènement sur la propriété diamètre.
    En vb.net, ça doit donner quelque-chose comme ça (si j'ai bien compris) dans la classe boulon :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    Public Property _diametre() As Double
            Get
                Return diametre
            End Get
            Set(ByVal value As Double)
                ecrou.diametre = value
                vis.diametre = value
            End Set
        End Property
    @DonQuiche
    est-il vraiment nécessaire que le graphe soit cohérent à tout instant ? Est-ce qu'on ne pourrait pas se contenter de valider son état à certains moments ?
    Non, je fais aussi de l'optimisation. Une fois l'objet crée par l'utilisateur, je boucle du calcul dessus en faisant varier certaines propriétés.

    Maintenant, j'imagine que tu es venu poser cette question parce que nombre de pièces ont des propriétés qui sont liées entre parent-enfants ?
    Oui, c'est courant. Tout est souvent imbriqué.

    Si oui je me tournerais plutôt vers un système automatisé basé sur la décoration par des attributs et l'usage de la réflexion.
    Touché !
    Je ne maîtrise pas du tout les attributs. Si c'est une bonne piste (???) pour mettre de l'ordre dans mes classes. Je vais regarder ça de près.

    @StringBuilder
    Et pourquoi pas mettre le diamètre dans une class abstraite dont héritent Boulon, Vis et Ecrou ?
    Encore touché !
    Pareil pour les classes abstraites. Mais bon, j'ai compris le principe.
    Par contre, je ne pense pas que cela convienne (voir ci-dessous).

    @DonQuiche
    L'ennui, c'est que j'imagine qu'une vis peut être utilisée pour autre chose qu'un boulon.
    Tout a fait. Je ne peux pas définir ma vis avec son élément d'assemblage. C'est pareil pour tout autre objet réel. Je ne peux pas définir tasse en fonction de ce que je vais mettre dedans, ni en fonction de l'endroit où je vais la poser.

  14. #14
    Membre expérimenté
    Homme Profil pro
    Inscrit en
    Février 2003
    Messages
    2 194
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : Belgique

    Informations forums :
    Inscription : Février 2003
    Messages : 2 194
    Par défaut
    Pour le code oui c'est bien ca
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
    Public Property Diametre() As Double
            Get
                Return _diametre
            End Get
            Set(ByVal value As Double)
                _diametre = value
                ecrou.Diametre = value
                vis.Diametre = value
            End Set
    End Property

  15. #15
    Membre confirmé
    Profil pro
    Inscrit en
    Décembre 2005
    Messages
    77
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2005
    Messages : 77
    Par défaut
    Bon, je retiens donc la méthode suivante.

    Quand je construis une classe (globale) utilisant d'autres classes (internes) qui ont des propriétés communes, il faut que :

    - je construise toutes mes classes internes de manière totalement indépendantes,
    - je redéclare toutes mes propriétés communes dans la classe globale et j'affecte les propriétés des éléments internes avec le set,

    Par contre, j'aime pas trop passer vis et écrou en private car il faut que je puisse exploiter les méthodes de vis et ecrou à partir de boulon.

    Et dans ces conditions je peux accéder à diamètre par 3 chemins :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    boulon.diametre
    boulon.vis.diametre
    boulon.ecrou.diametre
    Je peux masquer les deux derniers ?

  16. #16
    Expert confirmé
    Avatar de StringBuilder
    Homme Profil pro
    Chef de projets
    Inscrit en
    Février 2010
    Messages
    4 197
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Chef de projets
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2010
    Messages : 4 197
    Billets dans le blog
    1
    Par défaut
    Avec parent qui référence l'objet parent (le boulon dans le cas d'une vis) :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    int diametre
    {
       get
       {
         if (parent != null) throw new Exception("Vous êtes prié de passer par mon parent.");
         return _diametre;
       }
    }

  17. #17
    Membre Expert Avatar de DonQuiche
    Inscrit en
    Septembre 2010
    Messages
    2 741
    Détails du profil
    Informations forums :
    Inscription : Septembre 2010
    Messages : 2 741
    Par défaut
    Pour détailler la solution basée sur la réflexion, l'idée est d'avoir quelque chose de ce genre :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    class Boulon : class Element
    {
      [Match("Vis.Diameter")]
      [Match("Ecrou.Diameter")]
      public double Diameter { get; set; }
     
      public CEcrou Ecrou { get; set; }
     
      public CVis Vis { get; set; }
    }
    J'ai défini une classe de base "Element" dans laquelle on placera un parent lui aussi du type Element. Cela permettra, si on modifie une propriété sur un élément, d'interroger son parent.

    Puis, partant de là, on peut bricoler deux solutions :
    * Soit utiliser un outil comme PostSharp (aop) en étape de post-compilation pour générer automatiquement des méthodes SetDiameterFromUI sur Ecrou, Boulon et Vis et un routage vers les parents lors des changements de propriété. Evidemment on appellera cette méthode depuis l'UI pour obtenir le comportement que tu veux. Voici un tutorial qui montre comment utiliser PostSharp pour implémenter automatiquement INotifyPropertyChanged.

    * Soit générer une classe UIHelper qui se basera sur la réflexion pour faire ça de façon dynamique. L'idée est d'avoir une méthode UIHelper.Set(() => myEcrou.Diameter = 5) qui en plus d'exécuter le lambda interrogera les attributs de Ecrou et de son parent pour voir s'il faut répercuter le truc. La réflexion est lente (disons 10 fois plus qu'un code normal) mais ce n'est pas un problème si elle n'est appelée que lors des interactions utilisateurs. Et puis on peut carrément réduire le problème en générant des lambdas à la volée via les expressions si nécessaire. Côté implémentation, on délcare UIHelper.Set comme prenant en argument un objet Expression<Action> (ou quelque chose dans ce goût là) pour récupérer non pas un simple lambda mais un graphe syntaxique décrivant ce lambda (un noeud assignation ayant un élément propriété cible et un élément valeur constante).


    Par contre, attention : les deux cas demandent un certain temps de développement (quelques heures à deux jours si tu n'es pas familier de ces systèmes et selon ton expérience générale) et peuvent être fastidieux. D'autre part, le système gère le cas où deux propriétés doivent être égales entre un parent et son enfant mais rien de plus. Si tu as besoin d'un autre comportement où deux propriétés sont liées mais pas égales, tu dois étendre ton système qui peut vite devenir lourd, nécessiter beaucoup de temps de développement par nouveau comportement et ces comportements ne sont pas forcément aisément qualifiables par des attributs.

    Bref, pèse bien le pour et le contre avant de te lancer là-dedans. Peut-être est-il plus simple d'implémenter un routage de pseudo-événements en manuel (dans le setter de Diamètre de Vis on appelle Parent.OnChildrenPropertyChange("Diameter")). Mais tu voulais un système automatisé alors en voilà deux.

    En revanche, l'avantage du système automatisé, s'il convient bien à tes besoins (peu de comportements différents) est qu'après ça tu peux facilement l'étendre pour lui faire lister, par exemple, toutes les vis compatibles avec un boulon (mais pas avec un écrou où alors il faut de nouveaux attributs). Accessoirement, si tu n'as jamais fait ça, ça peut être intéressant de découvrir.

  18. #18
    Membre confirmé
    Profil pro
    Inscrit en
    Décembre 2005
    Messages
    77
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2005
    Messages : 77
    Par défaut
    Et bien quand je lis le dernier post de Donquiche, j'ai l'impression de revenir pas mal d'années en arrière quand j'ai commencé à coder.
    J'ai beaucoup de chemin à parcourir encore...

    Je pense que dans un premier temps, je vais passer par la manière de faire proposée par BenoitM. Je verrai dans la pratique, si ça va coller.

    Je marque comme résolu.

    Merci à tous pour vos propositions, vos pistes de reflexion.

  19. #19
    Membre expérimenté
    Homme Profil pro
    Inscrit en
    Février 2003
    Messages
    2 194
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : Belgique

    Informations forums :
    Inscription : Février 2003
    Messages : 2 194
    Par défaut
    Mettre la variable en private c'est pour proteger le code et donc ne pas avoir la possibiliter de faire
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    myBoulon.Vis.Diametre=5  
    myBoulon.Ecrou.Diametre=7
    mais c'est pas une obligation

    sinon il faut jouer avec des events pour prévenir la classe mere mais c'est lourd aussi

    donc je mettrai quand une methodes
    "CheckValidity" qui vérifie si les 2 diametres sont identique

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

Discussions similaires

  1. Programmation orientée objet ? Comment ?
    Par ..::snake::.. dans le forum Langages de programmation
    Réponses: 5
    Dernier message: 27/05/2007, 21h05
  2. Réponses: 1
    Dernier message: 28/03/2007, 15h33
  3. Cloner un objet : comment créer l'instance ?
    Par phplive dans le forum Langage
    Réponses: 8
    Dernier message: 29/05/2005, 18h27
  4. Réponses: 7
    Dernier message: 13/12/2004, 19h23
  5. comment programmer une progressbar
    Par Choucas dans le forum Paradox
    Réponses: 3
    Dernier message: 13/11/2002, 11h07

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