【问题标题】:Derived and base class, can I set the base explicitly?派生类和基类,我可以显式设置基类吗?
【发布时间】:2011-01-28 01:04:24
【问题描述】:
public class SuperCar: Car
{
     public bool SuperWheels { get {return true; } }
}

public class Car 
{
     public bool HasSteeringWheel { get {return true;} }
}

如何为派生的 Supercar 设置基类?

例如,我想像这样简单地设置 SuperCars 基类:

public void SetCar( Car car )
{
SuperCar scar = new SuperCar();
car.Base = car; 
}

基本上,如果我有 Car 对象,我不想手动遍历汽车的每个属性来设置 SuperCar 对象,我认为这是你可以做到的唯一方法,但如果你能做到其他方式会好得多。

【问题讨论】:

  • No. 简短原因:没有单独的基础对象(object)this == (object)base 总是正确的。不过,有一些方法可以通过反射(和其他方式)执行克隆/复制。或许描述一下真正想要什么:)
  • 虽然问题并没有直接询问反射(或复制构造函数),但我添加了标签以希望生成更有趣的相关问题列表。享受。 (stackoverflow.com/questions/3072518/… 看起来特别有趣,而且可能是重复的)
  • 我不太使用继承,所以很有可能有更好的方法来完成我真正想做的事情。基本上,我在 winforms 中使用 wcf ria 服务,但我使用的是 Janusys ui 套件,这需要我将服务代理创建的项目转换为 ITypelist。所以我试图简单地继承服务代理生成的类型以创建 ItemCollection : List, ItypedList
  • @Eric Lippert:听起来他所追求的甚至不是继承,而是他的对象或架构的更好结构。
  • 然而,从表面上看,这似乎是最容易做的事情。我需要所有基本属性加上 1 或 2 个附加属性。

标签: c# reflection copy-constructor derived-class


【解决方案1】:

我在子类中使用了类似的东西,它对我来说很好用:

using System.Reflection;
.
.
.
/// <summary> copy base class instance's property values to this object. </summary>
private void InitInhertedProperties (object baseClassInstance)
{
    foreach (PropertyInfo propertyInfo in baseClassInstance.GetType().GetProperties())
    {
        object value = propertyInfo.GetValue(baseClassInstance, null);
        if (null != value) propertyInfo.SetValue(this, value, null);
    }
}

【讨论】:

  • 是的。这是完美的。
【解决方案2】:

如果我正确理解了您的问题(而且我并不完全确定自己是否正确),那么您可以通过执行以下操作来获得您想要的行为:

class Car {
    public bool CarProperty { get; set; }
    // regular constructor
    public Car() {

    }
    // "copy" constructor
    public Car(Car c) {
        CarProperty = c.CarProperty;
    }
}

class SuperCar : Car {
    public bool SuperCarProperty { get; set; }
    // regular constructor
    public SuperCar() {
    }
    // "copy" constructor
    public SuperCar(Car c) : base(c) {
        SuperCar sc = c as SuperCar;
        if(sc != null) {
            SuperCarProperty = sc.SuperCarProperty;
        }
    }

那么你可以这样做:

public void SetCar(Car car) {
    SuperCar scar = new SuperCar(car);
}

请注意,您在“复制”构造函数中必须非常小心,不要以这样的方式复制属性,即两个对象在不应该共享相同成员(引用)时。

不过,我不得不问一下,你的目标是什么?

【讨论】:

  • 我的目标很简单。基本上,在现实生活中 Supercar 可能会有 100 种属性。所以可以说我现在维护一个超级跑车数据库。现在,我想从超级跑车继承,但我想传递我已经创建的超级跑车的基类,纯粹是为了方便。当我已经创建了基本类型时,我不想手动设置 100 个属性。
  • 听起来你需要将 SuperCar 分解成更小的对象。然后可以共享 SuperCars 之间相同的对象。
  • 我更关心我对c#中继承的理解。在我看来,如果 A 类派生自 B 类,你应该能够在 A 上设置 B。所以如果你有一个 A 类的实例,你应该能够说 A.B = new B();跨度>
  • 在我的梦想世界中,您可以像这样添加到类 A 以公开基 B: public B GetSetBase { get { return base;设置 { base = value;} }
  • 我认为您不太了解继承。继承是关于为一组对象定义形式,而不是为特定对象定义特定细节。对于后者,您想使用合成。
【解决方案3】:

这是不可能的。

您需要手动设置属性。

【讨论】:

  • 假设我有一个人员类,当然有成千上万个数据项代表人员类。 person 类定义了一万个属性。现在,我有一个与我想派生的特定人员类相关联的人员 ID,并创建一个从人员继承的“约翰”类。现在我知道了我想传入的特定人员 ID,这将是“John”的基础。
  • 你可以做一个包装器而不是使用继承。
【解决方案4】:

只能复制另一个类的内容,不能直接设置。请参阅下面使用所谓的复制构造函数的示例。

class Car
{
    string model;
    public Car(string model) { this.model = model; }
    protected Car(Car other) { this.model = other.model; }
    string Model { get; set; }
}

class SuperCar : Car
{
    public SuperCar(Car car) : base(car) { }
    public SuperCar(string model) : base(model) { }
    bool IsTurbo { get; set; }
}

关键是构造函数声明后的关键字base()

【讨论】:

  • 这很有趣,但它并不能真正解决迭代 30 个属性的问题,除非我完全遗漏了什么。
  • 如果需要手动设置属性,this answer 会更好地解释如何最好地使用复制构造函数。
【解决方案5】:

总体上有很多有用的 cmets。我认为 pst 给出了简短的答案,我认为这是正确的:

没有。简短的理由:没有单独的基础对象。 (object)this == (object)base 始终为真。不过,有一些方法可以通过反射(和其他方式)执行克隆/复制。或许描述一下真正想要的东西

所以,他关于使用 automapper 工具的建议也非常有用,基本上就是我想要的。

【讨论】:

    【解决方案6】:

    首先,每个 SuperCar 对象都彼此不同。 继承帮助您定义相关对象的共同行为,并不意味着它们是相同的对象。每个类型的对象都有自己的构造过程。在创建子对象之前,根据继承层次结构创建基类对象。如果您希望为所有 SuperCar 对象使用公共属性,则需要在 SuperCar 实例中维护 Car 对象的单独实例,将公共汽车对象分配给 SuperCar 中的汽车对象并覆盖从基础 Car 派生的属性对象并将其重定向到道具。内部 Car 对象。

    public class SuperCar: Car
    {
         public bool SuperWheels { get {return true; } }
    
         Car carInstance = null;
         public void SetCar( Car car )
         {
             carInstance = car; 
         }
    }
    

    但我仍然相信,按照您想要的方式,这种设计有问题。如果您可以让我们更全面地了解您为什么要这样做,我们可能会提出更好的设计来满足您的要求。

    【讨论】:

      【解决方案7】:

      如果您希望拥有比复制反射属性更多的控制权,请尝试应用 Builder 模式。 T 可以是从 BaseClass 派生的任何类。

       public static T BuildNew<T>(BaseClass baseClass) where T : BaseClass, new()
       {
          return new T
          {
              Property1 = baseModel.Property1,
              Property2 = baseModel.Property2,
          };
       }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2012-10-29
        • 1970-01-01
        • 2014-04-30
        • 1970-01-01
        • 2018-02-07
        • 2016-10-17
        • 1970-01-01
        • 2011-01-31
        相关资源
        最近更新 更多