2010-05-20 14 views
3
public class Car 
{ 
    private string make; 
    private string model; 
    public Car(string make, string model) 
    { 
     this.make = make; 
     this.model = model; 
    } 
    public virtual void Display() 
    { 
     Console.WriteLine("Make: {0}", make); 
     Console.WriteLine("Model: {0}", model); 
    } 
    public string Make 
    { 
     get{return make;} 
     set{make = value;} 
    } 
    public string Model 
    { 
     get{return model;} 
     set{model = value;} 
    } 
} 

public class SuperCar:Car 
{ 
    private Car car; 
    private int horsePower; 
    public SuperCar(Car car) 
    { 
     this.car = car; 
    } 
    public int HorsePower 
    { 
     get{return horsePower;} 
     set{horsepower = value;} 
    } 
    public override void Display() 
    { 
     base.Display(); 
     Console.WriteLine("I am a super car"); 
} 

Quand je fais quelque chose commeCréer une classe héritée de la classe de base

Car myCar = new Car("Porsche", "911"); 
SuperCar mySupcar = new SuperCar(myCar); 
mySupcar.Display(); 

Je ne reçois que « Je suis un supercar » mais pas les propriétés de ma classe de base. Dois-je affecter explicitement les propriétés de ma classe de base dans le constructeur SuperCar? En fait j'essaye le modèle de décorateur où je veux qu'une classe ajoute le comportement à une classe de base.

+1

pour Supercar être un vrai décorateur, déléguer tout o f Les méthodes de la voiture à votre voiture enveloppée. Il est discutable si Décorateur est le bon modèle ici, d'autant plus que vous avez affaire à des classes concrètes. – mdma

+2

Supposons que vous renommiez Car en Container et SuperCar en Box. Vous dites "Une boîte est une sorte de conteneur (parce qu'elle hérite de conteneur) et chaque boîte contient un conteneur (parce qu'il prend un conteneur dans son constructeur et l'enregistre dans un champ)". Est-ce réellement ce que vous voulez modéliser? Pourquoi une boîte devrait contenir un conteneur? Pourquoi une SuperCar devrait-elle contenir une voiture et être une sorte de voiture? –

Répondre

6

alternativement:

public class Car 
{ 
    public Car(string make, string model) 
    { 
     this.make = make; 
     this.model = model; 
    } 


    public Car (Car car):this(car.Make, Car.Model){} 
} 

public class SuperCar : Car 
{ 
    SuperCar(Car car): base(car){} 
} 

De cette façon, vous pouvez hériter une classe de voiture, et ont le contenu de la voiture de l'objet peupler fourni. Les objets hérités n'ont pas besoin de savoir quoi faire. Ils passent juste l'objet Car actuel sur la classe de base et font le travail.

0

Modifier les propriétés privées en propriétés protégées, privées ne sont accessibles par personne d'autre que la classe qui les crée, tandis que les variables héritées peuvent accéder aux variables protégées.

+0

Cela signifie-t-il que je devrai assigner explicitement les variables protégées des propriétés de l'objet Car que j'utilise pour créer l'objet SuperCar? – Raj

0

Yep pour obtenir ce travail que vous voulez, vous devez définir le constructeur de base comme ci-dessous:

public SuperCar(Car car):base(car.make,car.model) 
{ 
    this.car = car; 
} 
1

En regardant votre code, je ne sais pas comment il compile. Vos constructeurs ont tort car le constructeur de base ne saura pas comment exécuter un constructeur qui prend type car. Il semble que vous essayez d'implémenter le motif décorateur mais que vous ne l'avez pas fait correctement. Vraiment ce que vous devriez avoir est une interface ICar qui à la fois mettre en œuvre et de Display() en SuperCar vous devez appeler car.Display() Vous devrez également mettre en œuvre Marque et Modèle sur Super voiture et les rendre voiture.Make & voiture.Modèle pour mettre en œuvre le modèle de décorateur correctement.

public interface ICar 
{ 
    string Make {get; set;} 
    string Model {get; set;} 
    void Display(); 
} 

public class Car :ICar 
{ 
    private string make; 
    private string model; 
    public Car(string make, string model) 
    { 
     this.make = make; 
     this.model = model; 
    } 
    public virtual void Display() 
    { 
     Console.WriteLine("Make: {0}", make); 
     Console.WriteLine("Model: {0}", model); 
    } 
    public string Make 
    { 
     get{return make;} 
     set{make = value;} 
    } 
    public string Model 
    { 
     get{return model;} 
     set{model = value;} 
    } 
} 

public class SuperCar:ICar 
{ 
    private ICar car; 
    private int horsePower; 
    public SuperCar(ICar car) 
    { 
     this.car = car; 
    } 

    public string Make 
    { 
     get{return car.Make;} 
     set{car.Make = value;} 
    } 
    public string Model 
    { 
     get{return car.Model;} 
     set{car.Model = value;} 
    } 
    public int HorsePower 
    { 
     get{return horsePower;} 
     set{horsepower = value;} 
    } 
    public override void Display() 
    { 
     car.Display(); 
     Console.WriteLine("I am a super car"); 
} 
+0

J'ai accepté la réponse de Kevin parce que dans mon cas, je n'ai pas d'interface et je veux ajouter un comportement supplémentaire à une classe existante. Cependant, j'apprécie votre explication complète du motif décorateur. – Raj

+0

C'est une question si vous voulez utiliser le motif décorateur ou non. Vraiment, il semble que vous ne voulez pas le modèle décorateur parce que vous voulez juste étendre la voiture (qui est ce que l'héritage est pour) et ne pas envelopper et changer comment cela fonctionne, auquel cas Kevin est la bonne solution. –

0

Vous n'êtes pas tout à fait implémentez le decorator pattern

Vous avez besoin d'une classe de base abstraite pour tenir la voiture décorée

public abstract class CarDecorator 
    { 
    protected Car DecoratedCar { get; private set; } 

    protected CarDecorator(Car decoratedCar) 
    { 
     DecoratedCar = decoratedCar; 
    } 
    } 

    public class SuperCar : CarDecorator 
    { 
    public SuperCar(Car car) 
     : base(car) 
    { 
    } 
    public int HorsePower 
    { 
     get { return horsePower; } 
     set { horsepower = value; } 
    } 
    public override void Display() 
    { 
     DecoratedCar.Display() 
     Console.WriteLine("Plus I'm a super car."); 
    } 
    } 
+0

Mais puis-je affecter un objet SuperCar à un objet Car, par exemple ajouter un SuperCar à une liste ? – Raj

+0

Non, vous auriez besoin d'une liste de CarDecorators à la place. – Daniel

4

je pourrais être à venir dans un peu tard, mais seulement dans le événement que quelqu'un trouve ceci utile:

Vous pouvez utiliser la réflexion. Il faut un peu plus de code que ce que vous avez proposé, mais je pense qu'il offre toujours la brièveté que vous recherchez.

public SuperCar(Car car) 
{ 
    var props = typeof(Car).GetProperties().Where(p => !p.GetIndexParameters().Any()); 
    foreach (var prop in props) 
    { 
     prop.SetValue(this, prop.GetValue(car)); 
    } 

    // Set SuperCarcentric properties 
    // . 
    // . 
    // . 
} 

j'ai écrit explicitement de votre exemple pour illustrer clairement le concept, mais je pense que ce serait mieux fait une méthode générique qui peut être utilisé dans tous les cas similaires de votre solution.

Espérons que cela aide.

0

Sur la base de réponse @JoshWheelock j'ai écrit cette méthode que je mets dans un fichier partagé de mon projet Xamarin

Il clone cours, de sorte que vous pouvez utiliser pour dupliquer une base classe l'héritière, vous pouvez régler la T param

//... 
#if WINDOWS_UWP 
using System.Reflection; 
#endif 
//... 

public void CloneIn<T>(T src, T dest) 
{ 
#if WINDOWS_UWP 
    var props = typeof(T).GetTypeInfo().DeclaredProperties.Where(p => !p.GetIndexParameters().Any()); 
#else 
    var props = typeof(T).GetProperties().Where(p => !p.GetIndexParameters().Any()); 
#endif 
    foreach (var prop in props) 
    { 
     if(prop.SetMethod!=null) 
      prop.SetValue(dest, prop.GetValue(src)); 
    } 
} 

Pas encore testé dans Android et iOS, Android concernant j'ai mon émulateur qui fonctionne correctement arrêté soddenly depuis une semaine ...

Questions connexes