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 :

pointeur sur une classe utilisateur


Sujet :

C#

  1. #1
    maa
    maa est déconnecté
    Membre actif
    Avatar de maa
    Inscrit en
    Octobre 2005
    Messages
    672
    Détails du profil
    Informations personnelles :
    Âge : 40

    Informations forums :
    Inscription : Octobre 2005
    Messages : 672
    Points : 288
    Points
    288
    Par défaut pointeur sur une classe utilisateur
    Bonjour,

    étant donné 2 instances de classes utilisateurs, j'aimerai faire pointer l'adresse de l'une vers l'adresse de l'autre.
    Lorsque j'essaie de faire cela :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    unsafe
    {
         *instance1= &instance2;
    }
    j'obtiens l'erreur suivante :
    Cannot take the ardess of a variable of a managed type.


    Est-ce que je m'y prends mal ?

    merci d'avance pour votre aide.

  2. #2
    Membre éprouvé
    Profil pro
    Inscrit en
    Avril 2007
    Messages
    764
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2007
    Messages : 764
    Points : 909
    Points
    909
    Par défaut
    ...
    "Faire pointer l'adresse de l'une vers l'adresse de l'autre", cela veut dire qu'au final les deux variables désigneront vers le même objet, non ?
    Donc :
    et voilà, les deux variables instance1 et instance2 pointent vers la même référence...

    J'ai l'impression d'avoir loupé quelque chose
    Que veux-tu faire, plus précisément ?

  3. #3
    maa
    maa est déconnecté
    Membre actif
    Avatar de maa
    Inscrit en
    Octobre 2005
    Messages
    672
    Détails du profil
    Informations personnelles :
    Âge : 40

    Informations forums :
    Inscription : Octobre 2005
    Messages : 672
    Points : 288
    Points
    288
    Par défaut
    Je voudrais faire évoluer un objet vers un type dérivé. Etant donné par exemple une classe Personne et une classe Etudiant (héritant de Personne), j'aimerai transformer une instance de Personne en une instance d'étudiant. Attention, je veux que ça reste physiquement la même instance.
    J'avais dans l'idée de faire une méthode comme cela :

    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
     
            /// <summary>
            /// Fais évoluer un objet de type T vers le type S
            /// </summary>
            /// <typeparam name="T">Type d'origine</typeparam>
            /// <typeparam name="S">nouveau type (héritant du type d'origine)</typeparam>
            /// <param name="obj">objet à faire évoluer</param>
            private unsafe void EvolveType<T, S>(T obj) where S : T, new() where T : IDisposable
            {
                // on crée une nouvelle instance "newobj" du type dérivé.
                S newobj = new S();
     
                // par réfléxion on copie toutes les valeurs des propriétés de l'objet d'origine dans les propriétés du nouvel objet. 
                PropertyInfo[] propeties = typeof(T).GetProperties();
                Type typeOfS = typeof(S);
                foreach (PropertyInfo property in propeties)
                    typeOfS.GetProperty(property.Name).SetValue(newobj, property.GetValue(obj, null), null);
     
                // on fait pointer l'adresse du nouvel objet vers l'adresse de l'ancien. (c'est là que j'ai un soucis)
                *newobj = &obj;
     
                // on libère l'ancien objet. Il ne reste donc que le nouveau, qui a l'adresse de l'ancien, qui contient les mêmes valeurs de propriété et dont le type dérive du type d'origine.
                obj.Dispose();
            }

  4. #4
    Membre éprouvé
    Profil pro
    Inscrit en
    Avril 2007
    Messages
    764
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2007
    Messages : 764
    Points : 909
    Points
    909
    Par défaut
    Pour que ton objet de type T "pointe" vers le nouvel objet de type S, il suffit de faire :
    Bien sûr, quand tu le réutiliseras à l'extérieur de ta fonction, il sera toujours considéré comme étant de type T, et donc il faudra effectuer un cast pour utiliser les méthodes de S...

    Le problème est au niveau de la libération de l'ancien objet (Dispose())...
    Je dois avouer que je ne m'y connais pas trop dans ce domaine. Il me semble cependant que :
    - après l'instruction "obj = newobj;", comme plus aucune variable ne pointe vers l'ancient objet, il sera un jour ou l'autre récupéré par le GC, avec ou sans appel à "Dispose()" ; ce qui ne règle cependant pas le problème s'il est utile d'effectuer cette libération
    - avec ton code, il y a un problème : si on fait pointer obj vers newobj puis qu'on dispose de obj, c'est en fait le nouvel objet qu'on libère...

    Je *pense*, mais j'aimerais bien que quelqu'un confirme/infirme, que le code suivant correspondrait à ce que tu veux faire :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    obj.Dispose(); // on libère les ressources utilisées par l'ancien objet
    obj = newobj; // la référence pointe maintenant vers le nouvel objet

  5. #5
    maa
    maa est déconnecté
    Membre actif
    Avatar de maa
    Inscrit en
    Octobre 2005
    Messages
    672
    Détails du profil
    Informations personnelles :
    Âge : 40

    Informations forums :
    Inscription : Octobre 2005
    Messages : 672
    Points : 288
    Points
    288
    Par défaut
    Quand tu fais :

    tu crée une nouvelle instance de obj. On ne peut pas dire que l'objet à évolué vers le type hérité, mais plutôt qu'un autre objet du type hérité a été crée et a pris la place du premier...

  6. #6
    Membre éprouvé
    Profil pro
    Inscrit en
    Avril 2007
    Messages
    764
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2007
    Messages : 764
    Points : 909
    Points
    909
    Par défaut
    tu crée une nouvelle instance de obj.
    Je ne comprends pas. Il n'y a pas de "new" dans mon instruction, donc je ne suis pas en train de créer une nouvelle instance de quoi que ce soit. Et obj est un nom de variable, pas une classe...
    • obj est une variable, qui désigne une référence vers un objet de type T.
    • newobj est une variable, qui désigne une référence vers un objet de type S, nouvellement créé, et dans lequel on a copié les valeurs des propriétés de obj.
    • lors de l'instruction "obj = newobj", la valeur de la variable obj devient la valeur de la variable newobj, donc maintenant obj désigne la référence vers notre objet de type S.

    J'avoue que je ne comprends pas vraiment ton problème, ni ton besoin de passer par des pointeurs, notions rarement vues dans le code C#.
    J'ai l'impression que tu oublies que dans le cas d'une instance de classe, l'objet est toujours "passé par référence" (j'ai du mal avec le vocabulaire informatique, même quand je connais les concepts, donc peut-être n'est-ce pas le terme approprié)



    On ne peut pas dire que l'objet à évolué vers le type hérité, mais plutôt qu'un autre objet du type hérité a été crée et a pris la place du premier...
    Euh. N'est-ce pas là exactement ce que tu veux faire ? (en tous cas c'est exactement ce qui transparaît dans ton code)

  7. #7
    maa
    maa est déconnecté
    Membre actif
    Avatar de maa
    Inscrit en
    Octobre 2005
    Messages
    672
    Détails du profil
    Informations personnelles :
    Âge : 40

    Informations forums :
    Inscription : Octobre 2005
    Messages : 672
    Points : 288
    Points
    288
    Par défaut
    Je ne comprends pas. Il n'y a pas de "new" dans mon instruction, donc je ne suis pas en train de créer une nouvelle instance de quoi que ce soit. Et obj est un nom de variable, pas une classe...
    Oui excuse moi, je me suis mal exprimé. Ce que je voulais dire est que obj prend la valeur d'un nouvel objet. Ce que je voudrais c'est que obj reste lui même, mais gagne les méthodes, les propriétés d'un type hérité vers lequel il évolue. J'essayais de bidouiller avec les pointeurs pour arriver à cela mais la notion de pointeur m'est encore assez étrangère... il est possible que cela ne permette pas de répondre à mon problème.

    Un bout de code pour illustrer ce que j'attends :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
                Personne p1 = new Personne("maxime", 23);
                Personne p2 = p1;  // on sauvegarde cette personne dans une personne p2.
                Console.WriteLine(p1.Equals(p2)); //renvoi true logiquement.
                EvolveType<Personne, Professor>(ref p1); //on fait évoluer p1 vers le type Professor. (quand je dis "évoluer", c'est en fait seulement c'est ce que je cherche à faire. Ici je crée seulement un nouvel objet de type professeur et  je remplace mon ancien objet par lui)
                ((Professor)p1).Qualification = "mathématiques";
                Console.WriteLine(p1.Equals(p2)); //renvoi false car p1 est un nouvel objet qui n'est plus égal à celui d'origine.
    Ce que j'aimerais, et je sais pas si c'est possible, c'est que la dernière ligne revoie true, c'est à dire que l'objet n'ait pas subit d'affectation mais ait seulement évolué vers un type hérité.

  8. #8
    Membre éclairé
    Homme Profil pro
    Inscrit en
    Mai 2003
    Messages
    299
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : Suisse

    Informations professionnelles :
    Secteur : Industrie

    Informations forums :
    Inscription : Mai 2003
    Messages : 299
    Points : 886
    Points
    886
    Par défaut
    ton besoin ainsi que la solution proposée ds ton code me semble bien dangereux en .NET où le garbage collector fait son office...
    En gros, tu voudrais fait un cast Etudiant etudiant = (Etudiant) p;
    c est pas possible en c# managé un truc pareil si Edutiant hérite simplement de Personne. (le contraire est evidemment ok)
    Peut etre faudrait il passer par une interface, ou avoir un attribut Personne ds ta classe Etudiant.

    Pourquoi veux tu absolument que la référence reste identique? Comme dit avec le GarbageCollector, j aurais tendance à dire "on s en fout"

    Apres, pour avoir "true" avec Equals, il faut faire un override de GetEquals.
    Par contre, pour garantir que les refences sont les memes, c est avec Object.ReferenceEquals(a, b) qu' il faut jouer

    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
       public class Personne
        {
            private string nom;
     
            public string Nom
            {
                get { return this.nom; }
            }
     
            public Personne(string nom)
            {
                this.nom = nom;
            }
        }
     
        public class Etudiant
        {
            private string promo;
            private Personne p;
     
            public Etudiant(string nom, string promo)
            {
                p = new Personne(nom);
                this.promo = promo;
            }
     
            public Etudiant(Personne p, string promo)        
            {
                this.p = p;
                this.promo = promo;
            }
     
            public string Nom
            {
                get { return this.p.Nom; }
            }
     
            public override bool Equals(object obj)
            {
                if (obj is Personne)
                {
                    Personne pers = (Personne)obj;
                    return this.Nom == pers.Nom;
                }
                else return base.Equals(obj);
            }
     
            public override int GetHashCode()
            {
                return Nom.GetHashCode();
            }
        }        
     
     
    static void Main(string[] args)
            {
                Personne p = new Personne("toto");
                Etudiant e = new Etudiant(p, "2003");            
                Console.WriteLine(e.Nom);            
                Console.WriteLine(e.Equals(p)); // Object.Equals(e, p)
                Console.WriteLine(Object.ReferenceEquals(e, p));
            }

    ds ce code, Equals renvoie "true", mais pas ReferenceEquals. Il y a bien 2 objets différents, mais en quoi est ce génant?

  9. #9
    maa
    maa est déconnecté
    Membre actif
    Avatar de maa
    Inscrit en
    Octobre 2005
    Messages
    672
    Détails du profil
    Informations personnelles :
    Âge : 40

    Informations forums :
    Inscription : Octobre 2005
    Messages : 672
    Points : 288
    Points
    288
    Par défaut
    Pourquoi veux tu absolument que la référence reste identique? Comme dit avec le GarbageCollector, j aurais tendance à dire "on s en fout"
    La force que je vois dans le langage objet c'est qu'il reflète bien la réalité. Mais sur le point que j'évoque en ce moment je trouve que nom. Pour faire l'analogie avec le monde réel, dans mon exemple ci dessus :
    - On a une personne (qui n'est pas encore professeur).
    - On tue cet objet personne.
    - On la remplace par une personne clonée qui est en plus professeur.

    Moi ce que j'aimerais, c'est seulement faire évoluer cette personne vers le titre de professeur. C'est quand même plus sympathique non ?

    Concrètement, cela peut me servir dans le cas suivant :

    Côté base de donnée, j'ai toute sorte d'infos pour une personne. Des infos de base (nom, prénom,...), des infos concernant la personne en tant que professeur (qualification,...), ou encore tout autre info la concernant en tant qu'un type dérivé.
    Pour des raisons de performances, je ne souhaite pas rapatrier toutes les données dans mon objet quand je lance mon application. J'ai la plupart du temps seulement besoin des infos de base. Seulement à certains moment, j'ai besoin d'avoir les infos du type professeur.
    Je pourrais créer d'office un objet professeur et ne charger que les donnée concernant la personne, mais comment savoir plus tard dans mon programme si un objet Professeur dont les propriétés propres au professeur sont nulles parce qu'elles n'ont pas été chargées ou parce que les données sont nulles en base de données ?
    La solution que je vois est alors de créer un objet de chaque type. Quand on a besoin des données concernant la personne on charge l'objet personne, quand on besoin des des données concernant le professeur on charge l'objet professeur. Le problème est que les données sont alors dupliquées et la modification d'un des objets ne sera pas faite dans l'autre.
    Une autre solution à laquelle je pensais et de faire évoluer les types. On commence par charger des objets personnes. Si l'on a besoin des données concernant les professeurs on fait évoluer ces objets vers le type professeur et chargeant toutes les données propre aux professeurs dans les nouvelles propriétés acquises. On est ainsi assuré que si ces propriétés sont nulles, c'est qu'elle le sont aussi en base de données.

    Qu'en penses-tu ? Cette dernière solution est elle réalisable ? Sinon y en a t-il une autre à laquelle tu penses ?

  10. #10
    Membre éprouvé
    Profil pro
    Inscrit en
    Avril 2007
    Messages
    764
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2007
    Messages : 764
    Points : 909
    Points
    909
    Par défaut
    Ce que je voudrais c'est que obj reste lui même, mais gagne les méthodes, les propriétés d'un type hérité vers lequel il évolue.
    Pas possible en tant que tel...



    Je pense que le principe consistant à créer un nouvel objet, plus spécialisé, et à remplacer l'ancien est tout à fait valable :

    Je crée et je remplis des objet Personne que je range dans une liste listeDesPersonnes de type List<Personne> (pour l'exemple).
    Lorsque j'ai besoin des données "professeur", je crée un nouvel objet Professeur. Je le remplis soit en récupérant tout dans la base de données, soit en récupérant uniquement les données "professeur" et en copiant le reste depuis mon objet Personne. Puis je remplace dans listeDesPersonnes mon ancien objet par mon nouvel objet Professeur (tout à fait possible puisque Professeur hérite de Personne), et je peux éventuellement stocker mon objet Professeur dans une liste listeDesProfesseurs de type List<Professeur>.
    Alors, mon nouvel objet Professeur est listé dans listeDesPersonnes en tant que Personne et dans listeDesProfesseurs en tant que Professeur, mais il s'agit bien du même objet, donc toute modification effectuée dans une des deux listes, dans une des deux représentations, se répercutera dans l'autre représentation...

    Cela ne convient-il pas à ce que tu veux faire ?

  11. #11
    maa
    maa est déconnecté
    Membre actif
    Avatar de maa
    Inscrit en
    Octobre 2005
    Messages
    672
    Détails du profil
    Informations personnelles :
    Âge : 40

    Informations forums :
    Inscription : Octobre 2005
    Messages : 672
    Points : 288
    Points
    288
    Par défaut
    Ta solution me conviens assez bien.
    Peut-on quand même vérifier, par réflexion ou autre, qu'il n'y a pas des instances d'objets qui pointent vers la même adresse mémoire qu' obj avant de faire pointer obj vers un autre objet dérivé. Ceci afin de faire pointer également ces instance vers newobj ?
    Je ne comprends d'ailleurs pas que ça ne fasse pas automatiquement...

  12. #12
    Membre éprouvé
    Profil pro
    Inscrit en
    Avril 2007
    Messages
    764
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2007
    Messages : 764
    Points : 909
    Points
    909
    Par défaut
    Peut-on quand même vérifier, par réflexion ou autre, qu'il n'y a pas des instances d'objets qui pointent vers la même adresse mémoire qu' obj avant de faire pointer obj vers un autre objet dérivé. Ceci afin de faire pointer également ces instance vers newobj ?
    Là je vois ton problème...
    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
    class ClasseA
    {
    	ClasseB champB;
     
    	public ClasseA(ClasseB champB)
    	{
    		this.champB = champB;
    	}
    }
     
    class ClasseB
    {
    	int entier;
     
    	public ClasseB(int entier)
    	{
    		this.entier = entier;
    	}
    }
     
    static class Program
    {
    	static void Main()
    	{
    		ClasseB instanceB = new ClasseB(1);
    		ClasseA instanceA = new ClasseA(instanceB);
    		// instanceA.champB.entier = 1
    		ClasseB newInstanceB = new ClasseB(2);
    		instanceB = newInstanceB;
    		// instanceB.entier = 2 mais instanceA.champB.entier = 1 
    		// donc instanceA.champB est toujours l'ancien objet
    		//    alors qu'on voudrait que ce soit le nouveau...
    	}
    }

    Visiblement on ne peut pas utiliser les adresses des classes ("Cannot take the address of, get the size of, or declare a pointer to a managed type")
    Donc je ne vois pas...

    Peut-être avec des événements ? solution qui marche, mais assez contraignante et pas élégante du tout (donc donnée pour l'exemple et certainement à fignoler si utilisation) :
    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
    class ClasseA
    {
    	ClasseB champB;
     
    	public ClasseA(ClasseB champB)
    	{
    		this.champB = champB;
    		champB.ObjectChanged += new ClasseBChangedEventHandler(champB_objectChanged);
    	}
     
    	void champB_objectChanged(object sender, ClasseBChangedEventArgs e)
    	{
    		champB = e.NewInstance;
    	}
    }
     
    class ClasseB
    {
    	int entier;
     
    	public ClasseB(int entier)
    	{
    		this.entier = entier;
    	}
     
    	public static void Replace(ClasseB oldInstance, ClasseB newInstance)
    	{
    		oldInstance.WhenObjectChanged(new ClasseBChangedEventArgs(newInstance));
    		oldInstance = newInstance;
    	}
     
    	public event ClasseBChangedEventHandler ObjectChanged;
     
    	protected virtual void WhenObjectChanged(ClasseBChangedEventArgs e)
    	{
    		ClasseBChangedEventHandler handler = ObjectChanged;
    		if (handler != null)
    		{
    			handler(this, e);
    		}
    	}
    }
     
    class ClasseBChangedEventArgs : EventArgs
    {
    	ClasseB newInstance;
     
    	public ClasseBChangedEventArgs(ClasseB newInstance)
    	{
    		this.newInstance = newInstance;
    	}
     
    	public ClasseB NewInstance
    	{
    		get { return newInstance; }
    	}
    }
     
    delegate void ClasseBChangedEventHandler(object sender, ClasseBChangedEventArgs e);
     
    static class Program
    {
    	static void Main()
    	{
    		ClasseB instanceB = new ClasseB(1);
    		ClasseA instanceA = new ClasseA(instanceB);
    		ClasseB newInstanceB = new ClasseB(2);
    		ClasseB.Replace(instanceB, newInstanceB);
    	}
    }

  13. #13
    Membre éclairé
    Homme Profil pro
    Inscrit en
    Mai 2003
    Messages
    299
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 44
    Localisation : Suisse

    Informations professionnelles :
    Secteur : Industrie

    Informations forums :
    Inscription : Mai 2003
    Messages : 299
    Points : 886
    Points
    886
    Par défaut
    Citation Envoyé par maa
    La force que je vois dans le langage objet c'est qu'il reflète bien la réalité. Mais sur le point que j'évoque en ce moment je trouve que non.
    J ai bien saisi ce probleme, qui m d ailleur intrigué: cela semble si facile en langage naturel de penser à un qqn qui puisse etre tantot prof, tantot eleve suivant les besoins.
    C est vrai que c est pas si trivial à mettre en oeuvre ici. D un autre coté, c est exactement la meme chose que de vouloir transformer un chien en girafe, parce que les 2 sont des animaux...

    Pour en revenir à ton sujet, je dirais que ton design peut deja dependre du modele SQL.
    Mais sans aller jusqu'à là, puisque tu veux garder une seule instance / une adresse memoire, la solution la plus simple est d avoir qu une seule classe -> un seul objet à définir.
    Et ds cette classe, tu peux definir le role, i.e. suivant les besoins, affecter ou remettre à 0 des champs.
    On peut ajuter un peu en creant des classes internal qui regroupent ces champs.
    Tu gère le role de la personne via une enum par ex;
    Ensuite, tu as des methodes d'evolution ou tu set/unset ces objets.
    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
        internal class Identite
        { 
            private string nom;
            private int age;
     
            public Identite(string nom, int age)  // objet DAL / from SQL ?
            {
                this.nom = nom;
                this.age = age;
            }
        }
     
        internal class Prof
        {
            private string qualif;
     
            public Prof(string qualif)
            {
                this.qualif = qualif;
            }
        }
     
        internal class Etudiant
        {
            private string promo;
     
            public Etudiant(string promo)
            {
                this.promo = promo;
            }
        }   
     
        public class Personne
        {
            public enum Role { pProf, pEtudiant, none };
            private Identite id;
            private Role role = Role.none;
            private Prof prof = null;
            private Etudiant etudiant = null;
     
            public Personne(string nom, int age)
            {
                this.id = new Identite(nom, age);
            }
     
            public void SetProf(string qualif)
            {
                this.prof = new Prof(qualif);
                this.etudiant = null;
                this.role = Role.pProf;
            }                                  
        }
    Cela me semble bcp plus simple à utiliser et maintenir que de vouloir "créer un nouvel objet, plus spécialisé, et remplacer l'ancien".
    Cela rejoins ton idée "créer d'office un objet professeur et ne charger que les données concernant la personne".
    Quant au "comment savoir plus tard dans mon programme si un objet Professeur dont les propriétés propres au professeur sont nulles parce qu'elles n'ont pas été chargées ou parce que les données sont nulles en base de données ?", avec une enum simple comme sus citée, je ne vois pas le probleme: les load/save vers SQL ne se feront que ds les conditions limitées par le role.

  14. #14
    maa
    maa est déconnecté
    Membre actif
    Avatar de maa
    Inscrit en
    Octobre 2005
    Messages
    672
    Détails du profil
    Informations personnelles :
    Âge : 40

    Informations forums :
    Inscription : Octobre 2005
    Messages : 672
    Points : 288
    Points
    288
    Par défaut
    Astartee, tu as parfaitement compris mon problème. L'utilisation des événements est cependant très laborieuse si il faut gérer le cas de chaque propriété de type class.... Si j'avais seulement une méthode qui puisse, à partir d'une instance d'objet, retrouver toutes les références à cette instance... ça n'est vraiment pas possible ?

    Eric80, ta solution me conviens assez bien excepté le fait qu'il va falloir à chaque utilisation d'un objet vérifier la propriété Role indiquant si le l'objet à été chargé dans tel ou tel rôle... J'aimerais mieux la méthode ci-dessus si toutefois on peut retrouver toutes les références à une instance d'objet.

  15. #15
    Membre régulier Avatar de DonkeyMaster
    Profil pro
    Développeur informatique
    Inscrit en
    Novembre 2005
    Messages
    95
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Novembre 2005
    Messages : 95
    Points : 110
    Points
    110
    Par défaut Composite, Assert And Rock n Roll
    Je crois avoir compris où tu veux en venir.
    Pour résoudre ce problème, j'aurais utilisé le Design Pattern Composite.

    J'explique.

    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
     
    using System.Collections.Generic;
    public class DonneesEleve
    {
        string Nom;
        string Prenom;
    }
     
     
    public class DonneesProfesseur
    {
        List<string> Matieres;
    }
     
    public class Eleve
    {
        public DonneesEleve id;
    }
     
    public class Professeur : Eleve
    {
        public DonneesProfesseur curriculum;
        public Professeur (Eleve e) : base()
        {
            this.id = e.id;
        }
    }
    C'est un peu plus lourd à mettre en place et à manipuler, mais ça marche très bien dans ton cas. Et conceptuellement, ça marche très bien aussi.

    Quand à ton truc de chercher toutes les références à une classe, je vois bien une solution détournée, mais encore il faut faire attention.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     
    using System.Collections.Generic;
     
    public class Eleve
    {
        public static readonly List<Eleve> instances = new List<Eleve>();
        public Eleve ()
        {
            instances.Add( this );
        }
        #region Le reste de la classe
        #endregion
    }
    Est-ce que tu vois où je veux en venir?
    Le problème, c'est que pour que ça marche, il faut toujours penser à appeler le constructeur par défaut de la classe mère.
    Donc, dans tous les constructeurs de toutes les classes, il te faudra utiliser des this et des base le plus possible. Si tu en oublies 1, c'est toute la branche qui est menacée.
    Comme ça:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    public class Professeur {
        public Professeur() : base() {}
        public Professeur(Eleve e):this(){}
    }
    Et puis, franchement, c'est vraiment pas élégant.

    Ce que j'avais fait une fois, c'est que dans ma classe de base, j'ai un booléen privé qui dit si tel constructeur a été appelé, et toutes mes méthodes et properties commencent par
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Debug.Assert(bool, string)
    lien MSDN

    J'espère t'avoir donné plein d'idées dangereuses.

    Bon courage

  16. #16
    maa
    maa est déconnecté
    Membre actif
    Avatar de maa
    Inscrit en
    Octobre 2005
    Messages
    672
    Détails du profil
    Informations personnelles :
    Âge : 40

    Informations forums :
    Inscription : Octobre 2005
    Messages : 672
    Points : 288
    Points
    288
    Par défaut
    DonkeyMaster, to premier exemple ne réponds pas un mon problème il me semble. Tu instancies un nouvel objet Professeur à partir des données d'un élève, mais au final tu utilises 2 instances et les données sont dupliquées.

    Quand à lister toutes les instances d'une classe à chaque fois que tu en créer une, ça ne me conviens pas trop. Il faut modifier toutes les classes pour remplir des listes qui prenne pas mal d'espace mémoire, puis il faut les parcourir pour découvrir toutes les références à une instance... c'est un peu lourd.

    Sinon, j'ai découvert l'existence d'une classe Pointer, mais je ne vois pas trop à quoi elle sert. Quelqu'un à une idée ?

Discussions similaires

  1. Récupérer un pointeur sur une classe Singleton
    Par slake13 dans le forum Débuter
    Réponses: 7
    Dernier message: 18/11/2008, 18h01
  2. Réponses: 8
    Dernier message: 30/05/2006, 02h26
  3. [C++] pointeur sur une classe
    Par PH69 dans le forum Débuter
    Réponses: 1
    Dernier message: 21/11/2005, 23h08
  4. Réponses: 14
    Dernier message: 14/03/2005, 10h16
  5. [MFC] Problème pointeur sur une classe
    Par mick74 dans le forum MFC
    Réponses: 7
    Dernier message: 14/04/2004, 15h17

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