继承需要存储子类特定数据的数组的最佳方法是什么?

时间:2020-03-05 18:44:05  来源:igfitidea点击:

我正在尝试建立类似于以下内容的继承层次结构:

abstract class Vehicle
{
  public string Name;
  public List<Axle> Axles;
}

class Motorcycle : Vehicle
{
}

class Car : Vehicle
{
}

abstract class Axle
{
  public int Length;
  public void Turn(int numTurns) { ... }
}

class MotorcycleAxle : Axle
{
  public bool WheelAttached;
}

class CarAxle : Axle
{
  public bool LeftWheelAttached;
  public bool RightWheelAttached;
}

我只想将MotorcycleAxle对象存储在Motorcycle对象的Axles数组中,而将CarAxle对象存储在Car对象的Axles数组中。问题是没有办法重写子类中的数组来强制一个或者另一个。理想情况下,类似以下内容对Motorcycle类有效:

class Motorcycle : Vehicle
{
  public override List<MotorcycleAxle> Axles;
}

但类型必须在覆盖时匹配。我如何支持这种架构?在访问Axles成员的任何地方,我都只需要做很多运行时类型检查和转换吗?我不喜欢添加运行时类型检查,因为我们开始失去强类型和多态性的好处。在这种情况下,至少必须进行一些运行时检查,因为WheelAttached和Left / RightWheelAttached属性取决于类型,但是我想将它们最小化。

解决方案

回答

使用更多泛型

abstract class Vehicle<T> where T : Axle
{
  public string Name;
  public List<T> Axles;
}

class Motorcycle : Vehicle<MotorcycleAxle>
{
}

class Car : Vehicle<CarAxle>
{
}

abstract class Axle
{
  public int Length;
  public void Turn(int numTurns) { ... }
}

class MotorcycleAxle : Axle
{
  public bool WheelAttached;
}

class CarAxle : Axle
{
  public bool LeftWheelAttached;
  public bool RightWheelAttached;
}

回答

想到2个选项。 1正在使用泛型:

abstract class Vehicle<TAxle> where TAxle : Axle {
   public List<TAxle> Axles;
}

第二个使用阴影,并假定我们具有属性:

abstract class Vehicle {
   public IList<Axle> Axles { get; set; }
}

class Motorcyle : Vehicle {
   public new IList<MotorcycleAxle> Axles { get; set; }
}

class Car : Vehicle {
   public new IList<CarAxle> Axles { get; set; }
}

void Main() {
   Vehicle v = new Car();
   // v.Axles is IList<Axle>

   Car c = (Car) v;
   // c.Axles is IList<CarAxle>
   // ((Vehicle)c).Axles is IList<Axle>

遮盖的问题是我们有一个通用列表。不幸的是,我们不能将列表限制为仅包含CarAxle。另外,即使那里有继承链,也不能将List <Axle>强制转换为List <CarAxle>。我们必须将每个对象转换为新的List(尽管使用LINQ变得容易得多)。

我会自己去买仿制药。

回答

我问了一个类似的问题,并且得到了一个更好的答案,该问题与C#对协方差和反方差的支持有关。有关更多信息,请参见该讨论。