J'ai dit 3 classes, animal, chat et chien.
// calling code var x = new Animal("Rex"); // would like this to return a dog type var x = new Animal("Mittens"); // would like this to return a cat type if(x.GetType() == typeof(Dog)) { x.Bark(); } else { x.Meow(); } class Animal { public Animal(string name) { // check against some list of dog names ... find rex // return Animal of type Dog. // if not... // check against some list of cat names ... find mittens // return Animal of type Cat. } }
4 Réponses :
Ce que vous cherchez est soit un «constructeur virtuel» (pas possible dans C #), soit le motif d'usine.
class Animal { // Factory method public static Animal Create(string name) { Animal animal = null; ... // some logic based on 'name' animal = new Zebra(); return animal; } }
Non. Fondamentalement, le bon correctif consiste à utiliser une méthode statique pouvant créer une instance du type droit: ou ceci pourrait être une méthode em> instance em> dans un Fondamentalement, un AnimalFactory code> type (ou autre). Ce serait une approche plus extensible - l'usine pourrait implémenter une interface, par exemple et pourrait être injectée dans la classe qui devait créer les instances. Cela dépend vraiment du contexte, parfois, cette approche est trop excédée. P>
nouveau foo (...) code> appel toujours em> crée une instance de exactement em>
foo code>. Alors qu'une méthode statique déclarée avec un type de retour de
FOO code> peut renvoyer une référence à n'importe quel type compatible avec
FOO code>. P> p>
Non, je ne pense pas que cela soit possible dans la manière dont vous voulez.
Vous pouvez créer une classe statique qui a une méthode qui renvoie un animal basé sur un nom, par exemple P>
static Animal CreateAnimal(string name) { if(catList.Contains(name)) return new Cat(name"); else if(dogList.Contains(name)) return new Dog(name); return null; }
Les autres réponses montrent que vous devez utiliser un motif d'usine, mais je voulais vous donner un exemple plus "pratique" de la façon dont vous le feriez. J'ai fait exactement ce que vous avez fait, mais je travaillais avec le imprimante EPL2 Langue . Quand j'ai vu (J'ai écrit ce Il y a longtemps donc je suis Bien sûr, certaines des choses que j'ai pouvais être améliorées sur). p> la manière dont le code fonctionne est que j'utilise le singleton modèle pour créer un classe d'usine afin que les gens puissent appeler Lors de l'initialisation, j'utilise la réflexion pour trouver des classes prenant en charge l'interface Lorsque vous essayez de créer la commande L'usine lève la commande d'imprimante dans le dictionnaire et crée le Classe correcte, il transmet ensuite la chaîne de commande complète sur cette classe pour un traitement ultérieur. P> Voici une copie d'une classe de commande et ses parents si vous vouliez le voir P> rectangle code>: p> x code>, je devais créer une instance de classe
rectangle code>, quand j'ai vu
a code> je devais créer une instance de classe
Texte code>.
var commande = epl2commandfactory.instance.createepl2command ("...") code>; en passant dans la chaîne de commande EPL2 et renvoie une instance de la classe qui représente cette classe spécifique. p>
IEPL2GeneralFactoryProduise code>, si le La classe prend en charge l'interface de l'usine stocke le code d'un ou deux lettres représentant la commande d'imprimante dans un dictionnaire de types. p>
drawableItembase code>: p>
EPL2CommandBase Code>: P>
public interface IEpl2GeneralFactoryProduct
{
string GetFactoryKey();
}
public interface IEpl2Command
{
string CommandString { get; set; }
}
public interface IDrawableCommand : IEpl2Command
{
void Paint(System.Drawing.Graphics g, System.Drawing.Image buffer);
}
Pas réellement sans vous limiter ... Votre classe de base devrait connaître ses sous-classes, ce qui n'est pas très utile.