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

C# Discussion :

Association entre classes et objet en lecture seule


Sujet :

C#

  1. #1
    Rédacteur

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Mars 2002
    Messages
    608
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Mars 2002
    Messages : 608
    Points : 1 561
    Points
    1 561
    Par défaut Association entre classes et objet en lecture seule
    Bonjour,

    Je débute dans la programmation purement objet, en particulier dans le passage du relationnel à l'objet, et je fais un tout petit programme de gestion avec ado pour apprendre.

    Disons que l'on a une classe LigneCommande qui représente une ligne d'une commande et une classe Produit. Chaque ligne de commande concerne un produit. Donc dans la classe LigneCommande on aura par exemple, entre autres :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    class LigneCommande
        {
            private Produit produit;
     
            public Produit LeProduit
            {
                get
                    {return produit;}
                set
                    {produit = value;}
            }
        }
    Ce qui permet d'accéder au produit de la ligne de commande, pour afficher son libellé par exemple :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    LigneCommande ligne = new LigneCommande();
    //...
    string libelle_produit = ligne.LeProduit.Libelle;
    Mais une ligne de commande ne doit pas servir à modifier un produit, or rien ne m'empêche de faire :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    Produit pdt = ligne.LeProduit;
    pdt.Prix *=10;
    pdt.Update(); //enregistre dans la base
    Comme je vois les choses, le produit qui est contenu dans la ligne de commande devrait être en lecture seule. Comment vous faites ? Vous mettez que l'identifiant du produit au lieu de l'objet entier dans LigneCommande ? Vous codez de la même façon en laissant le problème ? Certaines de vos classes ont un mode "lecture seule" qui va lever une exception si l'on essaie de modifier un attribut alors que l'objet est en lecture seule ? Ou vous mettriez le produit en private dans LigneCommande:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    class LigneCommande
    {
            private Produit produit;
     
            public float PrixDuProduit
            {
                get { return produit.Prix; }
            }
    }
    Ce qui peut être embêtant j'imagine si l'on a besoin d'accéder à beaucoup d'attributs de l'objet encapsulé.

    Merci !

  2. #2
    Membre éclairé Avatar de chamamo
    Profil pro
    Inscrit en
    Juin 2006
    Messages
    588
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2006
    Messages : 588
    Points : 735
    Points
    735
    Par défaut
    pour rendre une propriété en lecture seule, tu devrais mettre le set en private

    dans ton exemple, dans ta classe Produit tu drvais mettre le set de la proriété Prix en private

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    class Produit
        {
            private float prix;
     
            public float Prix
            {
                get
                    {return prix;}
                private set
                    {prix= value;}
            }
        }

  3. #3
    Membre éclairé Avatar de ppphil
    Profil pro
    Inscrit en
    Juin 2007
    Messages
    612
    Détails du profil
    Informations personnelles :
    Localisation : Suisse

    Informations forums :
    Inscription : Juin 2007
    Messages : 612
    Points : 685
    Points
    685
    Par défaut
    Ben non, du moment qu'il y a déjà un champ privé pour le prix...
    Les modification du prix se font en interne via le champ
    Les accès externes se font via la propriété en lecture seule
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    public float Prix
            {
                get  {return prix;}
            }
    Idem pour le produit dans la ligne de commande...

  4. #4
    Rédacteur

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Mars 2002
    Messages
    608
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Mars 2002
    Messages : 608
    Points : 1 561
    Points
    1 561
    Par défaut
    Citation Envoyé par chamamo Voir le message
    pour rendre une propriété en lecture seule, tu devrais mettre le set en private

    dans ton exemple, dans ta classe Produit tu drvais mettre le set de la proriété Prix en private
    Non parce qu'il faut pouvoir modifier le prix d'un produit. Si on ne peut pas le modifier de l'extérieur comment on fait ?

    Le problème n'est pas que l'on puisse modifier le prix d'une instance de la classe Produit, ça c'est normal. Le problème c'est qu'une instance de LigneCommande permette de modifier un produit.

    Citation Envoyé par ppphil
    Idem pour le produit dans la ligne de commande...
    C'est-à-dire ?

    Si tu fais :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    class LigneCommande
        {
            private Produit produit;
     
            public Produit LeProduit
            {
                get
                    {return produit;}
                private set
                    {produit = value;}
            }
        }
    Tu ne pourras pas modifier la référence "produit" pour qu'elle pointe sur autre chose, mais tu pourras accéder aux propriétés du produit et modifier son état, alors que le produit dans LigneCommande ne devrait servir qu'en lecture seule.

    Donc il est normal qu'on puisse faire :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    Produit pdt = new Produit();
    // ...
    pdt.prix = 10;
    pdt.Update();
    Et:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    LigneCommande ligne = new LigneCommande();
    //...
    string libelle_produit = ligne.LeProduit.Libelle;
    Mais, à mon sens, pas:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    Produit pdt = ligne.LeProduit;
    pdt.Prix *=10;
    pdt.Update(); //enregistre dans la base
    Ceux qui ont déjà développé des applis vraiment de façon orientée objet se sont forcément posé la question, non ?

  5. #5
    Membre éclairé Avatar de chamamo
    Profil pro
    Inscrit en
    Juin 2006
    Messages
    588
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2006
    Messages : 588
    Points : 735
    Points
    735
    Par défaut
    si je comprend bien, tu permets la modification des attributs du Produit si l'objet n'appartient pas a une LigneCommande, ce que je propose c'est tester si le produit appartient a une commande, si c'est le cas tu lèves une exception

    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
    class Produit 
        {
            public Produit ()
           {
           }
     
            public Produit (LigneCommande ligneCommande)
           {
                this.ligneCommande=ligneCommande;
           }
     
            private LigneCommande ligneCommande;
            private float prix;
     
            public float Prix
            {
                get
                    {return prix;}
                set
                    {
                     if(LigneCommande==null) throw new Exception("erreur");
                     prix= value;
                    }
            }
        }
    je ne sais pas si ça répond à ta question.

  6. #6
    Membre éclairé Avatar de ppphil
    Profil pro
    Inscrit en
    Juin 2007
    Messages
    612
    Détails du profil
    Informations personnelles :
    Localisation : Suisse

    Informations forums :
    Inscription : Juin 2007
    Messages : 612
    Points : 685
    Points
    685
    Par défaut
    Désolé, j'ai réfléchi un peu de travers...

    Ou alors comme ceci :
    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
      public class Produit
      {
        private float prix;
     
        public float Prix { get { return prix; } }
     
        public Produit(float aPrix)
        {
          prix = aPrix;
        }
      }
     
      public class Commande
      {
        private Produit prod;
     
        public Produit Prod { get { return prod; } }
     
        public Commande(Produit produit)
        {
          prod = produit;
        }
      }
     
     
       Produit prod = new Produit(2.45f);
       Commande cmd = new Commande(prod);

  7. #7
    Rédacteur

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Mars 2002
    Messages
    608
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Mars 2002
    Messages : 608
    Points : 1 561
    Points
    1 561
    Par défaut
    Merci à vous deux pour votre aide

    Chamano, oui ta proposition est assez proche de ce que j'appelle dans mon 1er post "faire un mode lecture seule de la classe". Ca revient à ça. On pourrait aussi passer un booléen dans le constructeur qui indique si on peut modifier ou pas l'objet.

    ppphil avec ta proposition tu encapsules la référence qui pointe sur le produit mais tu n'empêches pas de modifier l'état du produit par l'intermédiaire de LigneCommande.

    Je viens de trouver encore une autre solution mais pas très propre : faire une version de Produit qui n'est pas persistant (donc qui n'a pas la méthode Update() pour enregistrer dans la base).

    Ce que je cherchais surtout ce sont les techniques que vous avez choisi pour vos applis en ce qui concerne ce problème. D'autres avis ?

    Merci

  8. #8
    Membre éclairé Avatar de ppphil
    Profil pro
    Inscrit en
    Juin 2007
    Messages
    612
    Détails du profil
    Informations personnelles :
    Localisation : Suisse

    Informations forums :
    Inscription : Juin 2007
    Messages : 612
    Points : 685
    Points
    685
    Par défaut
    Citation Envoyé par Nightfall Voir le message
    ppphil avec ta proposition tu encapsules la référence qui pointe sur le produit mais tu n'empêches pas de modifier l'état du produit par l'intermédiaire de LigneCommande.
    A ben non, justement...
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    Produit prod = new Produit(2.45f);
    Commande cmd = new Commande(prod);
     
    cmd.Prod = new Produit(3.25f); //Impossible !!
    cmd.Prod.Prix = 4.36f; //Impossible !!

  9. #9
    Membre éclairé Avatar de chamamo
    Profil pro
    Inscrit en
    Juin 2006
    Messages
    588
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2006
    Messages : 588
    Points : 735
    Points
    735
    Par défaut
    Citation Envoyé par ppphil Voir le message
    A ben non, justement...
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    Produit prod = new Produit(2.45f);
    Commande cmd = new Commande(prod);
     
    cmd.Prod = new Produit(3.25f); //Impossible !!
    cmd.Prod.Prix = 4.36f; //Impossible !!
    et tu met la Méthode Update dans la classe Commande, et c'est réglé

  10. #10
    Rédacteur

    Homme Profil pro
    Développeur informatique
    Inscrit en
    Mars 2002
    Messages
    608
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Mars 2002
    Messages : 608
    Points : 1 561
    Points
    1 561
    Par défaut
    Citation Envoyé par ppphil Voir le message
    A ben non, justement...
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    Produit prod = new Produit(2.45f);
    Commande cmd = new Commande(prod);
     
    cmd.Prod = new Produit(3.25f); //Impossible !!
    cmd.Prod.Prix = 4.36f; //Impossible !!
    Oui tu règles le problème pour une propriété en passant son initialisation dans le constructeur, mais dans une appli un objet a pas une seule propriété, il en a une ou plusieurs dizaines, on peut pas toutes les passer dans le constructeur. Et qu'est-ce que tu fais si une méthode de l'objet permet de modifier son état ? Il faut raisonner sur l'objet dans son ensemble, pas sur une seule propriété.

    Citation Envoyé par chamamo
    et tu met la Méthode Update dans la classe Commande, et c'est réglé
    Je vois pas comment tu peux expliquer conceptuellement que c'est une classe commande qui est chargée de modifier un produit dans la base

  11. #11
    Membre éclairé Avatar de chamamo
    Profil pro
    Inscrit en
    Juin 2006
    Messages
    588
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2006
    Messages : 588
    Points : 735
    Points
    735
    Par défaut
    si la solution de ppphil ne t'arrange pas, je ne vois pas d'autres solutions à part tester dans le Set de tes propriétés si la modification vient de la commande ou d'ailleurs.

Discussions similaires

  1. Association entre classes en java
    Par Mystic eyes dans le forum Rational
    Réponses: 2
    Dernier message: 07/03/2011, 09h20
  2. [Access 2003]- erreur 3027 : base ou objet en lecture seule
    Par metallica_fr dans le forum Access
    Réponses: 5
    Dernier message: 15/12/2006, 17h36
  3. Mise à jour impossible, objet en lecture seule
    Par Pitou5464 dans le forum Access
    Réponses: 3
    Dernier message: 12/09/2006, 18h26
  4. Base de Données ou objet en lecture seule?
    Par ben_skywalker dans le forum Access
    Réponses: 6
    Dernier message: 01/06/2006, 08h47
  5. Réponses: 3
    Dernier message: 09/02/2006, 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