Search code examples
c#oopinheritancecovariancecontravariance

What is the best way to inherit an array that needs to store subclass specific data?


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:

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.


Solution

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