¿Cuál es la mejor manera de heredar una matriz que necesita almacenar datos específicos de subclases?

StackOverflow https://stackoverflow.com/questions/31088

Pregunta

Estoy intentando configurar una jerarquía de herencia similar a la siguiente:

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

Me gustaría almacenar solo objetos MotorcycleAxle en la matriz Axles de un objeto Motorcycle y objetos CarAxle en la matriz Axles de un objeto Car.El problema es que no hay manera de anular la matriz en la subclase para forzar uno u otro.Lo ideal sería que algo como lo siguiente fuera válido para la clase Motos:

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

pero los tipos deben coincidir al anular.¿Cómo puedo soportar esta arquitectura?¿Tendré que hacer muchas comprobaciones y transmisiones de tipos en tiempo de ejecución dondequiera que se acceda al miembro de Axles?No me gusta agregar verificaciones de tipo en tiempo de ejecución porque comienzas a perder los beneficios de la escritura fuerte y el polimorfismo.Tiene que haber al menos algunas comprobaciones en tiempo de ejecución en este escenario ya que las propiedades WheelAttached y Left/RightWheelAttached dependen del tipo, pero me gustaría minimizarlas.

¿Fue útil?

Solución

Utilice más genéricos

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

Otros consejos

Me vienen a la mente 2 opciones.1 está usando genéricos:

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

El segundo usa sombreado, y esto supone que tienes propiedades:

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>

El problema con el sombreado es que tienes una Lista genérica.Desafortunadamente, no puede restringir la lista para que solo contenga CarAxle.Además, no puede convertir un List<Axle> en List<CarAxle>, aunque haya una cadena de herencia allí.Tienes que convertir cada objeto en una nueva Lista (aunque eso se vuelve mucho más fácil con LINQ).

Yo también optaría por los genéricos.

le pregunté a pregunta similar y obtuve una mejor respuesta, el problema está relacionado con el soporte de C# para covarianza y contravarianza.Vea esa discusión para un poco más de información.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top