从基类创建继承类

Posted

技术标签:

【中文标题】从基类创建继承类【英文标题】:Create inherited class from base class 【发布时间】:2011-02-21 23:25:28 【问题描述】:
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
    
       getreturn make;
       setmake = value;
    
    public string Model
    
       getreturn model;
       setmodel = value;
    


public class SuperCar:Car

    private Car car;
    private int horsePower;
    public SuperCar(Car car)
    
        this.car = car;
    
    public int HorsePower
    
       getreturn horsePower;
       sethorsepower = value;
    
    public override void Display()
    
       base.Display();
       Console.WriteLine("I am a super car");

当我做类似的事情时

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

我只得到“我是一辆超级跑车”,但没有得到我的基类的属性。我应该在 SuperCar 构造函数中明确分配我的基类的属性吗?事实上,我正在尝试装饰器模式,我希望一个类向基类添加行为。

【问题讨论】:

为了让 Supercar 成为真正的装饰者,请将 Car 的所有方法委托给您的包裹汽车。如果 Decorator 是正确的模式,这是值得怀疑的,尤其是当您处理具体的类时。 假设您将 Car 重命名为 Container 并将 SuperCar 重命名为 Box。你说“盒子是一种容器(因为它继承自容器),每个盒子都包含一个容器(因为它在其构造函数中接受一个容器并将其保存在一个字段中)”。这真的是你想要建模的吗?为什么一个盒子应该包含一个容器?为什么 SuperCar 既包含 Car 又是 Car 的一种? 【参考方案1】:

或者:

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)

通过这种方式,您可以从 car 继承任何类,并从提供的对象中填充 car 内容。继承的对象不需要知道要设置什么。他们只是将当前的 Car 对象传递给基类,它就完成了工作。

【讨论】:

【参考方案2】:

我可能来晚了一点,但万一有人觉得这很有用:

您可以使用反射。它需要的代码比您建议的多一点,但我认为它仍然提供您正在搜索的简洁性。

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
    // .
    // .
    // .

我从您的示例中明确地写了这个来清楚地说明这个概念,但我认为这最好是一种通用方法,可以在您的解决方案的所有类似实例中使用。

希望这会有所帮助。

【讨论】:

【参考方案3】:

查看您的代码,我不确定它是如何编译的。您的构造函数是错误的,因为基本构造函数不知道如何运行采用 car 类型的构造函数。看起来您正在尝试实现装饰器模式,但没有正确完成。真正你应该拥有的是一个ICar 接口,它既可以实现,又可以从SuperCar 中的Display() 调用car.Display() 你还必须在超级汽车上实现Make 和Model 并让它们返回car.Make & car.Model 来正确实现装饰器模式。

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
    
       getreturn make;
       setmake = value;
    
    public string Model
    
       getreturn model;
       setmodel = value;
    


public class SuperCar:ICar

    private ICar car;
    private int horsePower;
    public SuperCar(ICar car)
    
        this.car = car;
    

    public string Make
    
       getreturn car.Make;
       setcar.Make = value;
    
    public string Model
    
       getreturn car.Model;
       setcar.Model = value;
    
    public int HorsePower
    
       getreturn horsePower;
       sethorsepower = value;
    
    public override void Display()
    
       car.Display();
       Console.WriteLine("I am a super car");

【讨论】:

我接受了凯文的回答,因为在我的情况下,我没有接口,我想向现有类添加额外的行为。但是,我感谢您对装饰器模式的完整解释。 是否使用装饰器模式是一个问题。真的,听起来您不想要装饰器模式,因为您只想扩展汽车(这就是继承的用途)而不是包装它并改变它的工作方式,在这种情况下,Kevin's 是正确的解决方案。【参考方案4】:

你没有完全实现decorator pattern

你需要一个抽象基类来保存装饰好的汽车

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

【讨论】:

但是我可以将 SuperCar 对象分配给 Car 对象,例如将 SuperCar 添加到 List 吗? 不,您需要一份 CarDecorators 列表。【参考方案5】:

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

【讨论】:

这是否意味着我必须从用于创建 SuperCar 对象的 Car 对象属性中显式分配受保护的变量?【参考方案6】:

是的,要让它按照你的意愿工作,你需要设置基本构造函数,如下所示:

public SuperCar(Car car):base(car.make,car.model)

  this.car = car;

【讨论】:

【参考方案7】:

基于@JoshWheelock 的回答,我编写了这个方法,并将其放入我的 Xamarin 项目的共享文件中

它克隆类,所以你可以用来复制继承人的基类,你可以调整 T 参数

//...
#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));
    

尚未在 androidios 中进行测试,关于 Android,我的模拟器一周后就彻底停止了正常工作......

【讨论】:

以上是关于从基类创建继承类的主要内容,如果未能解决你的问题,请参考以下文章

在 Kotlin 中使用 Jpa 注释从基类继承父属性

从基类到不同派生类的多重继承转换

错误:与 'operator=' 不匹配。试图从基类继承并从基类初始化?

如何通过派生类函数从基类更改向量

C# 使用new 关键字显式隐藏从基类继承的成员和内部类的使用

如何从基类动态创建派生类