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 :

Héritage d'instance statique


Sujet :

C#

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre confirmé
    Profil pro
    Inscrit en
    Mai 2002
    Messages
    208
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2002
    Messages : 208
    Par défaut Héritage d'instance statique
    Bonjour,

    J'ai une classe de base avec une propriété statique afin de renvoyer une instance unique.

    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
     
    public class MyBase
    {
           protected statique MyBase oCurrentInstance;
     
           public static MyBase Current
           {
                   get
                   {
                           if(object.ReferenceEquals(oCurrentInstance, null))
                           {
                                       oCurrentInstance = new MyBase();
                                       oCurrentInstance.Load();
                           }
                           return oCurrentInstance;
                   }
           }
    }
    Je voudrai créer des classes qui héritent de cette classe, est-il possible de modifier la propriété Current pour que l'instance soit du type de la classe héritée sans avoir à surcharger la propriété dans toutes les classes héritantes?
    En fait, je cherche un équivalent à :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    oCurrentInstance = this.GetType().CreateInstance();
    mais en static cela n'est pas possible

  2. #2
    Membre émérite
    Homme Profil pro
    Développeur / architecte
    Inscrit en
    Juillet 2009
    Messages
    473
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Développeur / architecte

    Informations forums :
    Inscription : Juillet 2009
    Messages : 473
    Par défaut
    Hello,

    J'ai peut-être pas tout compris sur ce que tu essaies de faire, mais tu ne peux pas surcharger ta propriété Current (car statique). En tout cas ça s'appelle un singleton ce que tu viens d'écrire.
    Je n'ai pas compris si tu dois avoir une seule instance quelle que soit le sous type, ou au max une de chaque type.??
    Je pense que si tu vas voir du côté du pattern fabrique abstraite tu devrais trouver ton bonheur (en cobinant singleton + fabrique abstraite). Je suppose qu'il y a bien un paramètre qui va te faire instancier une classe plutôt qu'une autre.

    Christophe

  3. #3
    Membre confirmé
    Profil pro
    Inscrit en
    Mai 2002
    Messages
    208
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2002
    Messages : 208
    Par défaut
    Tel que ma classe de base est écrite (cf mail précédent), je suis obligé de faire dans chaque classe héritante :
    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
    public class InheritedClass:MyBase
    {
    	public static new InheritedClass Current
    	{
    		get
    		{	
    			if(object.ReferenceEquals(cCurrentInstance, null))
    			{
    				cCurrentInstance = new InheritedClass();
    				cCurrentInstance.Load();
    			}
    			return (InheritedClass)cCurrentInstance;
    		}
    	}
    }
    et l'appel est :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    MyBase oBase = InheritedClass.Current
    J'aimerai ne pas écrire le code de InheritedClass, mais que la classe de base récupère le type appelant (cf le code de l'appel) et crée une instance de ce type. C'est pourquoi je pensais à this.GetType().CreateInstance()

    Une factory ne va pas m'aider car je ne souhaite pas appeler une méthode je veux rester avec ma propriété Current qui est déjà une factory en soit... sauf que cette factory ne connais pas le type de l'objet à créer d'où mon problème!

  4. #4
    Membre émérite
    Homme Profil pro
    Développeur / architecte
    Inscrit en
    Juillet 2009
    Messages
    473
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Développeur / architecte

    Informations forums :
    Inscription : Juillet 2009
    Messages : 473
    Par défaut
    Tu ne peux pas utiliser "this", puisque c'est une méthode statique, et en plus elle n'est pas encore instanciée.
    Mais à quel niveau sais-tu quelle classe doit être instanciée?
    Et sinon, par rapport à mon autre question:
    Je n'ai pas compris si tu dois avoir une seule instance quelle que soit le sous type, ou au max une de chaque type.?
    Sinon, en continuant sur ton idée, on peut faire un truc du style (mais je vois un intérêt limité, autant écrire une méthode "Current" par classe):
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    public static MyBase GetCurrent(type o)
    {
    //on retourne une instance du type donné
    }
    je suppose qu'il y a même moyen de mettre un generic la dessus.

    A+

  5. #5
    Membre confirmé
    Profil pro
    Inscrit en
    Mai 2002
    Messages
    208
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2002
    Messages : 208
    Par défaut
    Mais à quel niveau sais-tu quelle classe doit être instanciée?
    C'est l'appel qui détermine le type :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    MyBase oBase = InheritedClass.Current
    oBase est de type InheritedClass donc dans Current je cherche à savoir sur quel classe l'appel a eu lieu

    Je n'ai pas compris si tu dois avoir une seule instance quelle que soit le sous type, ou au max une de chaque type.?
    au max une de chaque type

    Je suppose qu'il y a bien un paramètre qui va te faire instancier une classe plutôt qu'une autre
    Oui, le type sur lequel a été fait d'appel

    Sinon, en continuant sur ton idée, on peut faire un truc du style (mais je vois un intérêt limité, autant écrire une méthode "Current" par classe):
    Oui j'ai bien pensé faire
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    public static MyBase GetCurrent<T>() where T : MyBase, new()
    {
    	if(object.ReferenceEquals(cCurrentInstance, null))
    	{
    		cCurrentInstance = new T();
    		cCurrentInstance.Load();
    	}
    	return (T)cCurrentInstance;
     
    }
    Mais je voudrais garder la propriété Current pour ne pas modifier tous les appels existant.

    Question: une proprité générique ça existe???

  6. #6
    Membre confirmé
    Profil pro
    Inscrit en
    Mai 2002
    Messages
    208
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2002
    Messages : 208
    Par défaut
    @cinemania :

    Merci cela correspond bien à ce que je veux faire mais as tu une solution pour faire ça en tant que propriété de la classe de base?

  7. #7
    Membre émérite
    Homme Profil pro
    Développeur / architecte
    Inscrit en
    Juillet 2009
    Messages
    473
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bas Rhin (Alsace)

    Informations professionnelles :
    Activité : Développeur / architecte

    Informations forums :
    Inscription : Juillet 2009
    Messages : 473
    Par défaut
    Peut être que ce lien pourra t'aider?

  8. #8
    Membre Expert
    Profil pro
    Inscrit en
    Juillet 2006
    Messages
    1 103
    Détails du profil
    Informations personnelles :
    Âge : 47
    Localisation : France, Meurthe et Moselle (Lorraine)

    Informations forums :
    Inscription : Juillet 2006
    Messages : 1 103
    Par défaut
    Quelque soit le langage, on ne peut pas redéfinir une méthode static, on peut au mieux la cacher pour la "remplacer"/"occulter".

    Si j'ai bien compris ton problème tu souhaite que chacune des classes qui héritent ne soit instanciables qu'une seule et unique fois via le design pattern du Singleton.

    En fait la problématique, c'est qu'il sera possible d'instancier toutes les classes de ton arbre au moins une fois et tu risque d'avoir des problèmes ne termes d'instances...

    Si seule une et seule et unique classe héritière doit pouvoir être instanciée en fonction de celle qui te choisi pour une exécution de ton appli donnée, je te suggère de mettre le champ dans la classe ancêtre et un code de propriété spécifique appelant une méthode ancêtre (tjs en static) qui vérifie que l'instance n'est pas déja définie

    utiliser une méthode static dans la classe de base utilisant les generics te permettrait d'instancier dynamiquement la bonne sans réécrire systèmatiquement le code, surtout si cette méthode de construction est de type protected.

    Il faut savoir parfois sortir des sentiers battus et faire abstraction des design pattern.

    tu peux même utiliser un dictionary static caché dans l'ancêtre avec un Type comme clé, et une instance de ce même Type comme valeur.
    (donc object) et tu fait un cast au niveau de ton accesseur get sur le singleton de ton héritière...

    voici un code qui pourrait remplir tes besoins
    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
     
    public abstract class SingletonBase
    {
        protected static Dictionary<Type, object> s_Singletons;
        protected static T CreateSingleton<T>() where T: SingletonBase, new()
        {
            lock (typeof(SingletonBase))
            {
                if (s_Singletons == null) s_Singleton = new Dictionary<Type, object>();
                T single = null;
                if (!s_Singletons.TryGetValue(typeof(T), out single))
                    s_Singletons.Add(typeof(T), single = new T());
                return single;
            }
        }
    }
    public class MyBase : SingletonBase
    {
        public static MyBase Singleton { get { return CreateSingleton<MyBase>(); } }
     
    //...
        private MyBase() 
        {
        }
    }
    public class MyInherits : MyBase
    {
        public static new MyInherits Singleton { get { return CreateSingleton<MyInherits>(); } }
     
    //...
     
        private MyInherits : base()
        {
        }
    }
    j'ai juste un petit doute sur le code de SingletonBase...
    effectivement j'ai imposé que les classes décrites par T devaient être instanciable, mais j'ignore si cette portabilité ne va pas poser problème

    si les "domaines" de visibilité devaient poser problème tu peux remplacer le code de la méthode généric par ceci :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
        protected static T CreateSingleton<T>() where T: SingletonBase
        {
            lock (typeof(SingletonBase))
            {
                if (s_Singletons == null) s_Singleton = new Dictionary<Type, object>();
                T single = null;
                if (!s_Singletons.TryGetValue(typeof(T), out single))
                    s_Singletons.Add(typeof(T), (T)Activator.CreateInstance(typeof(T), true));
                return single;
            }
        }
    Personellement je déteste utiliser ce type de code et préfere utiliser une singleton factory qui est seule à pouvoir instancier les classes que je dois possèder sous forme d'instances unique,

    d'ailleurs ce code n'est qu'une abstraction de la singleton factory remise directement dans la classe qui utilise le singleton, mais je trouve que cette écriture n'est pas heureuse, car tu mélange alors les concepts.
    il est préférable à mon sens de recourrir à une factory externe qui instanciera le type en ayant recours à la reflection.
    Certes je sais la reflection c'est long, blablabla, mais là on parle de singletons... donc la perte de temps inhérente au mécanisme de reflection est ici un sacrifice que l'on peut aisément consentir.

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

Discussions similaires

  1. Héritage et variable statique
    Par darkrojo dans le forum Débuter
    Réponses: 9
    Dernier message: 10/08/2011, 13h52
  2. [PHP 5.0] [POO] Héritages de variables statiques
    Par LogistiX dans le forum Langage
    Réponses: 7
    Dernier message: 21/01/2009, 18h07
  3. héritage de méthodes statiques
    Par behess dans le forum Design Patterns
    Réponses: 8
    Dernier message: 15/09/2008, 18h14
  4. [héritage] Héritage et champs statiques.
    Par salome dans le forum Langage
    Réponses: 4
    Dernier message: 03/04/2005, 20h21
  5. [héritage] Héritage et champs statiques.
    Par salome dans le forum Langage
    Réponses: 2
    Dernier message: 02/04/2005, 00h11

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