2010-08-22 17 views
15

Je me sens comme je l'ai sauté une classe C# ou deux, mais voici mon dilemme:C# abstrait héritage classe champ statique

J'ai une classe abstraite dont je tire plusieurs classes d'enfants.

Je sais avec certitude que pour chacune des classes enfants, je vais avoir un constructeur qui a besoin d'un certain objet statique en tant que modèle et cet objet sera différent pour chacune des classes enfants. Ma première approche consistait à créer un objet statique public dans la classe parente abstraite, puis, avant de commencer à créer des instances des classes enfants, je le modifiais pour chacun d'entre eux, mais il s'avère que ne fait en réalité qu'un seul objet statique, pour la classe abstraite, et chacune de ses classes enfant l'utilise.

Comment pourrais-je résoudre le problème?

Pour être plus précis, voici le pseudo-code:

La classe abstraite parent:

abstract class AbstractClass 
{ 
    static public ModelObject Model; 
    ... 
} 

Une des classes d'enfants:

class Child : AbstractClass 
{ 
    ... 
    public Child() 
    { 
     this.someField = Model.someField; 
    } 
} 

EDIT:

Le Le modèle doit être membre de la classe "ModelObject", il ne doit PAS être un singleton ou un anythi ng d'autre.

EDIT2:

Pour être encore plus précis, j'ai choisi cette mise en œuvre pour un jeu d'échecs: J'ai une classe abstraite pour les pièces d'échecs et les classes d'enfants représentent les pièces en béton du jeu: pions, chevaliers , etc. La classe abstraite hérite de MeshMatObject, une classe qui représente les objets 3d génériques avec les fonctionnalités de base, comme les rotations, les maillages, les matériaux, les textures etc. Elle définit des méthodes abstraites pour les pièces de jeu d'échecs, comme GetPossibleMoves(). L'objet Model dont je parlais plus haut est un membre de MeshMatObject et, à mon avis, devrait être défini en dehors de la classe une seule fois et ensuite utilisé pour toutes les pièces. Je veux dire: par exemple tous les pions ont le même maillage et la même texture, donc je ne vois pas l'intérêt de donner un modèle en tant que paramètre chaque fois que vous voulez faire un pion.

+2

De quelle manière AbstractClass doit-il accéder au modèle? – dtb

+2

Vous devriez envisager de passer une instance Model aux constructeurs de vos sous-classes au lieu d'utiliser un tel champ statique. – Trillian

+0

Je suis d'accord avec Trillian. Avoir le modèle statique viole vraiment l'esprit de l'encapsulation ici. –

Répondre

6

J'ai tendance à utiliser quelque chose de similaire à la solution de @ shf301.En fonction de vos besoins, il peut être utile de configurer la classe de base comme:

abstract class AbstractClass 
{ 
} 

abstract class AbstractClass<TModel> : AbstractClass 
    where TModel : ModelObject 
{ 
    static public TModel Model; 
    ... 
} 

Cela me permet une classe de base commune que je peux travailler avec des fonctions non génériques. Cela permet également aux types dérivés de choisir le type de modèle exact et de réduire le nombre de castings.

+0

Ca marche parfaitement! Juste que les "..." sont sur "AbstractClass". Une implémentation agréable et simple, merci. Encore une chose: y a-t-il une pénalité de performance ou autre avec cette implémentation? Je ne vois pas pourquoi cela devrait être le cas, en particulier avec la fonctionnalité "optimiser le code" de VS, mais juste en assurer. – cantrem

+0

EDIT: Dans mon cas, la contrainte de type devrait être AbstractClass; alors les classes d'enfants seraient déclarées comme shf301 indique. C'est parce que j'ai besoin de l'implémentation juste pour les enfants de AbstractClass. quelque chose comme: AbstractClass : AbstractClass où T: AbstractClass et l'enfant: ChildClass: AbstractClass cantrem

15

Vous pouvez contourner le champ statique partagé en rendant votre classe abstraite générique. Chaque classe générique obtiendra sa propre copie des champs statiques.

abstract class AbstractClass<T> 
{ 
    static public ModelObject Model; 
    ... 
} 

Ensuite, chaque classe enfant utilisera une instance différente du champ statique.

class Child : AbstractClass<Child> 
{ 
    ... 
    public Child() 
    { 
     this.someField = Model.someField; 
    } 
} 

Peu importe que AbstractClass ne fasse pas référence au paramètre générique. Vous l'utilisez uniquement pour donner à chaque classe enfant une instance unique de la classe de base.

+1

Merci pour l'entrée, c'est à mi-chemin là. L'autre moitié vient de Justin R. Si je n'avais utilisé que votre solution, je n'aurais eu aucun moyen de fonctionner avec seulement des objets AbstractClass. Par exemple, j'aurais eu du mal à trouver un tableau 2D de pièces d'échecs abstraites. De toute façon, il est très bon de savoir qu'avec des classes génériques, chaque enfant reçoit une copie du champ statique. – cantrem

3

Que diriez-vous d'une usine de découpler vos classes à partir d'un modèle hérité:

public static class ModelObjectFactory 
{ 
    public static ModelObject GetModel<T>(T obj) 
    { 
     // return ModelObject according to type of parameter 
    } 
} 

class Child 
{ 
    public Child() 
    { 
     ModelObject mo = ModelObjectFactory(this); 
     this.someField = mo.someField; 
    } 
} 
+0

Une usine aurait mieux fonctionné dans d'autres cas. Dans ce cas particulier, je pense que j'aurais trop compliqué (si c'est un mot) la situation; mais merci pour l'idée! – cantrem

+0

Avoir des objets avec une seule responsabilité ne complique jamais les choses. Vérifiez les principes SOLID. -1 au commentaire si c'était possible :) –