Quelle est la meilleure façon d'hériter d'un tableau qui doit stocker des données spécifiques à une sous-classe ?

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

Question

J'essaie de mettre en place une hiérarchie d'héritage similaire à la suivante :

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

Je souhaite stocker uniquement les objets MotorcycleAxle dans le tableau Axles d'un objet Motorcycle et les objets CarAxle dans le tableau Axles d'un objet Car.Le problème est qu'il n'y a aucun moyen de remplacer le tableau dans la sous-classe pour forcer l'un ou l'autre.Idéalement, quelque chose comme ce qui suit serait valable pour la classe Moto :

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

mais les types doivent correspondre lors du remplacement.Comment puis-je prendre en charge cette architecture ?Vais-je simplement devoir effectuer de nombreuses vérifications et conversions de types au moment de l'exécution partout où le membre Axles est accessible ?Je n'aime pas ajouter des vérifications de type à l'exécution, car vous commencez à perdre les avantages d'un typage fort et du polymorphisme.Il doit y avoir au moins quelques vérifications d'exécution dans ce scénario puisque les propriétés WheelAttached et Left/RightWheelAttached dépendent du type, mais j'aimerais les minimiser.

Était-ce utile?

La solution

Utilisez plus de génériques

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

Autres conseils

2 options me viennent à l’esprit.1 utilise des génériques :

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

La seconde utilise l'observation - et cela suppose que vous ayez des propriétés :

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>

Le problème avec l'observation est que vous disposez d'une liste générique.Malheureusement, vous ne pouvez pas limiter la liste à contenir uniquement CarAxle.De plus, vous ne pouvez pas convertir un List<Axle> en List<CarAxle> - même s'il existe une chaîne d'héritage.Vous devez convertir chaque objet dans une nouvelle liste (bien que cela devienne beaucoup plus facile avec LINQ).

J'opterais moi-même pour des génériques.

J'ai demandé à un question similaire et obtenu une meilleure réponse, le problème est lié à la prise en charge par C# de la covariance et de la contravariance.Voir cette discussion pour un peu plus d'informations.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top