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

时间:2022-12-08 13:02:02

I'm trying to set up an inheritance hierarchy similar to the following:

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

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

I would like to only store MotorcycleAxle objects in a Motorcycle object's Axles array, and CarAxle objects in a Car object's Axles array. The problem is there is no way to override the array in the subclass to force one or the other. Ideally something like the following would be valid for the Motorcycle class:

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

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

but the types have to match when overriding. How can I support this architecture? Will I just have to do a lot of run-time type checking and casting wherever the Axles member is accessed? I don't like adding run-time type checks because you start to lose the benefits of strong typing and polymorphism. There have to be at least some run-time checks in this scenario since the WheelAttached and Left/RightWheelAttached properties depend on the type, but I would like to minimize them.

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

3 个解决方案

#1


5  

Use more generics

使用更多泛型

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


0  

2 options spring to mind. 1 is using generics:

我想到了两个选择。 1是使用泛型:

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

The second uses shadowing - and this assumes you have properties:

第二个使用阴影 - 这假设你有属性:

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>

The problem with shadowing is that you have a generic List. Unfortunately, you can't constrain the list to only contain CarAxle. Also, you can't cast a List<Axle> into List<CarAxle> - even though there's an inheritance chain there. You have to cast each object into a new List (though that becomes much easier with LINQ).

阴影的问题是你有一个通用的List。不幸的是,您不能将列表限制为仅包含CarAxle。此外,您无法将List 强制转换为List - 即使存在继承链。您必须将每个对象转换为新的List(尽管使用LINQ会变得更容易)。

I'd go for generics myself.

我自己去寻找仿制药。

#3


0  

I asked a similar question and got a better answer, the problem is related to C#'s support for covariance and contravariance. See that discussion for a little more information.

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

#1


5  

Use more generics

使用更多泛型

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


0  

2 options spring to mind. 1 is using generics:

我想到了两个选择。 1是使用泛型:

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

The second uses shadowing - and this assumes you have properties:

第二个使用阴影 - 这假设你有属性:

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>

The problem with shadowing is that you have a generic List. Unfortunately, you can't constrain the list to only contain CarAxle. Also, you can't cast a List<Axle> into List<CarAxle> - even though there's an inheritance chain there. You have to cast each object into a new List (though that becomes much easier with LINQ).

阴影的问题是你有一个通用的List。不幸的是,您不能将列表限制为仅包含CarAxle。此外,您无法将List 强制转换为List - 即使存在继承链。您必须将每个对象转换为新的List(尽管使用LINQ会变得更容易)。

I'd go for generics myself.

我自己去寻找仿制药。

#3


0  

I asked a similar question and got a better answer, the problem is related to C#'s support for covariance and contravariance. See that discussion for a little more information.

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