views:

83

answers:

5
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");
}

When I do something like

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

I only get "I am a supercar" but not the properties of my base class. Should I explicitly assign the properties of my base class in the SuperCar constructor? In fact I'm trying Decorator pattern where I want a class to add behaviour to a base class.

A: 

Change the private properties to protected properties, private are not accessible by anyone except the class that creates them, while protected variables could be accessed by inherited classes.

jpabluz
Does this mean that I'll have to explicitly assign the protected variables from the Car object properties that I'm using to create the SuperCar object?
Raj
A: 

alternatively:

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){}
}

This way you can inherit any class from car, and have the car contents populate from the provided object. The inherited objects don't need to know anything about what to set. They just pass the current Car object onto the base class and it does the work.

Kevin
A: 

yep to get this to work as you want you need to set the base constructor like below:

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

Looking at your code I am not sure how it compiles. Your constructors are wrong because the base constructor won't know how to run a constructor that takes type car. It looks like you are trying to implement the decorator pattern but have not done it correctly. Really what you should have is an ICar interface that both implement and from Display() in SuperCar you should call car.Display() You'll also have to implement Make and Model on Super car and make them return car.Make & car.Model to implement the decorator pattern properly.

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");
}
Craig Suchanec
I've accepted Kevin's answer because in my case I don't have an interface and I want to add additional behaviour to an existing class. However, I appreciate your full explanation of the decorator pattern.
Raj
Its a matter if you want to use the decorator pattern or not. Really it sounds like you don't want the decorator pattern because you just want to expand the car (which is what inheritance is for) and not wrap it and change how it works, in which case Kevin's is the proper solution.
Craig Suchanec
A: 

You are not quite implementing the decorator pattern

You need an abstract base class to hold the decorated car

  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.");
    }
  }
Daniel
But can I assign a SuperCar object to a Car object, e.g add a SuperCar to a List<Car> ?
Raj
No you would need a list of CarDecorators instead.
Daniel