简体   繁体   中英

Create inherited class from base class

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.

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.

I might be coming in a little late here, but just in the event that someone finds this useful:

You can use reflection. It requires a little more code than what you proposed, but I think it still offers the brevity you're searching for.

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

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

I wrote this explicitly from your example to clearly illustrate the concept, but I think this would be best made a generic method that can be used in all similar instances of your solution.

Hope this helps.

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

将私有属性更改为受保护的属性,除了创建它们的类之外,任何人都无法访问private,而受保护的变量可以由继承的类访问。

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;
}

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

Based on @JoshWheelock answer I wrote this method that I put in a shared file of my Xamarin project

It clones classes, so you can use to duplicate a base classe the heiress, you could adjust the 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));
    }
}

Not yet tested in Android and iOS, concerning Android I have my emulator that soddenly stopped working properly since a week ...

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM