2009-04-01 8 views
1

Quelle est la meilleure façon d'implémenter une stratégie pour le constructeur d'une classe template/abstract en C#? J'ai plusieurs classes qui sont toutes basées sur l'analyse d'une chaîne dans le constructeur. L'analyse est effectuée dans une méthode statique qui crée une liste de paires de valeurs clés et est commune à toutes les classes, mais certains champs sont également communs à toutes les classes. J'utilise donc une classe de modèle abstrait.Implémentation d'une stratégie pour le constructeur

Le problème est que je ne vois pas un moyen d'hériter de l'implémentation du constructeur de la classe de base abstraite. Sinon, j'implémenterais la stratégie du constructeur dans la classe de base et forcerais le traitement des listes à l'intérieur de certaines méthodes abstraites.

Edit: Ajouté pas le code de travail pour la classe modèle

public abstract class XXXMessageTemplate 
{ 
    public XXXMessageTemplate(string x) // implementation for the constructor 
    { 
     Parse(x);//general parse function 
     CommonFields();//filling common properties 
     HandlePrivateProperties();//fill individual properties 
     HandlePrivateStructures();//fill individual structures 
    } 
    abstract void HandlePrivateProperties(); 
    abstract void HandlePrivateStructures(); 
} 

The actual messages should not implement any constructor and only implement the HandlePrivateProperties and HandlePrivateStructures functions. 

Répondre

7

Si vous voulez que la logique du constructeur de la classe de base pour fonctionner dans la classe dérivée, que vous auriez normalement juste appeler jusqu'à ce:

public Derived(...) : base(...) 
{ 
    // ... 
} 

la classe de base peut abstraite d'appel/méthodes virtuelles au cours du constructeur, mais il est généralement mal vus comme corps du constructeur de la classe dérivée n'aura pas encore été exécuté. (Vous voudriez documenter cela avec insistance.)

Est-ce que cela répond à votre question? Je ne suis pas tout à fait sûr de comprendre le problème - un pseudo-code serait utile.

EDIT: Les classes dérivées ont pour implémenter des constructeurs. Les constructeurs ne sont pas hérités. Si vous ne spécifiez aucun constructeur, le compilateur fournira un constructeur sans paramètre qui appelle un constructeur sans paramètre de base. Cependant, vous pouvez facilement écrire un constructeur avec la même signature et il suffit d'appeler le constructeur de la classe de base:

public Derived(string x) : base(x) 
{ 
    // Base constructor will do all the work 
} 
+0

Je ajout d'un pseudo-code pour rendre l'émetteur plus propre ... – weismat

+0

O k - cela signifie que mon intension est impossible à forcer le modèle de stratégie ici - je dois implémenter ensuite un constructeur qui appelle un constructeur de nom de fonction protégée qui appelle alors les fonctions Handle. Me rappelle la restriction qu'un constructeur ne peut pas appeler un autre constructo d'une classe. – weismat

+0

Les constructeurs peuvent appeler des constructeurs d'autres classes - vous pouvez écrire "object o = new object()" par exemple. Vous ne pouvez pas essayer d'utiliser un autre constructeur comme faisant partie de votre propre chaîne de constructeurs - cela n'aurait pas beaucoup de sens. –

2

Fournir un constructeur pour la classe de base et l'utiliser dans les classes dérivées:

abstract class Base { 
    // ... 
    protected Base(string commonField) { 
     CommonField = commonField; 
    } 
} 

class Derived1 : Base { 
    public Derived1(string commonField, string specificField) : base(commonField) { 
     SpecificField = specificField; 
    } 
} 
1

I Je ne suis pas sûr à 100% que je comprends parfaitement la question, mais voulez-vous dire que vous voulez que vos sous-classes transmettent une chaîne littérale à la base, comme dans cet exemple?

public class MyMessage : XXXMessageTemplate 
{ 
    public MyMessage() : base("MyMessage String") 
    { 
    } 

    public override void HandlePrivateProperties() 
    { 
     // ... 
    } 

    public override void HandlePrivateStructures() 
    { 
     // ... 
    } 
} 
1

Comme je peux le voir, le problème est dans la méthode Parse (...). Pas dans la méthode elle-même mais dans son existence. Vous avez des données brutes (chaîne x) qui doivent être converties en données structurées (paires de valeurs clés) avant d'être utilisées pour construire des objets. Vous avez donc besoin de transmettre des données structurées dans des constructeurs de base et enfants. Je vois 3 approches:

  1. Analyser les données dans la classe de base et utiliser la propriété de base protégée pour la transmettre aux enfants.
  2. Analyser les données avant d'appeler le constructeur.
  3. Analyser les données en lieu et place de l'utilisation.

Vous pouvez prolonger une réponse Mehrdad via la propriété protégée supplémentaire qui détient args analysables.Quelque chose comme:

abstract class Base { 
    protected ParsedData ParsedData; 
    // ... 
    protected Base(string x) { 
     ParsedData = Parse(x); 
     CommonFields(); //initialize common fields using ParsedData 
    } 
} 

class Derived1 : Base { 
    public Derived1(string x) : base(x) { 
     DerivedFields(); //initialize specific fields using ParsedData 
    } 
} 

Ou vous pouvez passer une pré chaîne analysable dans le constructeur:

abstract class Base { 
    protected ParsedData ParsedData; 
    // ... 
    public static ParsedData Parse(string x) 
    { 
     //Parse x here... 
    } 

    protected Base(ParsedData data) { 
     CommonFields(data); //initialize common fields using data 
    } 
} 

class Derived1 : Base { 
    public Derived1(ParsedData data) : base(data) { 
     DerivedFields(data); //initialize specific fields using data 
    } 
} 

Ou analyser en place d'utilisation:

abstract class Base { 
    // ... 
    protected Base(string x) { 
     var data = Parse(x); 
     CommonFields(data); //initialize common fields using data 
    } 
} 

class Derived1 : Base { 
    public Derived1(string x) : base(x) { 
     var data = Parse(x); 
     DerivedFields(data); //initialize specific fields using data 
    } 
} 
+0

Approche intéressante - la méthode d'analyse est en fait actuellement dans la classe de base et l'objet résultant n'est pas conservé - dans une certaine mesure également aux restrictions de mémoire. Je suis surpris que vous damnez la fonction d'analyse comme le problème, mais cela semble logique. – weismat

+0

Désolé, oubliez de mentionner le désavantage de la méthode n ° 1: les données analysées resteront jusqu'à l'objet GCed. Il n'y a pas non plus de moyen facile d'effacer ce champ, car à un constructeur particulier vous ne savez pas si un autre enfant existe ou pas. – Aleksei

Questions connexes