2008-08-27 23 views
2

Je suis en train de mettre en place une hiérarchie d'héritage semblable à ce qui suit:Quelle est la meilleure façon d'hériter un tableau qui doit stocker des données spécifiques à une sous-classe?

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 voudrais seulement stocker des objets MotorcycleAxle dans un array d'objets de moto Essieux et objets CarAxle dans un array d'objets de voiture Axles. 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 en cas de dépassement. Comment puis-je soutenir cette architecture? Est-ce que je devrai faire beaucoup de vérification de type et de lancement au moment de l'exécution, où que l'on accède au membre Axles? Je n'aime pas ajouter des vérifications de type au moment de l'exécution, car vous commencez à perdre les avantages de la typage et du polymorphisme. Il doit y avoir au moins quelques vérifications au moment de l'exécution dans ce scénario puisque les propriétés WheelAttached et Left/RightWheelAttached dépendent du type, mais je voudrais les minimiser.

Répondre

5

Utilisez plus 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; 
} 
0

2 options à l'esprit. 1 est l'utilisation de médicaments génériques:

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

La seconde utilise shadowing - et cela suppose que vous avez 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 shadowing est que vous avez une liste générique. Malheureusement, vous ne pouvez pas contraindre la liste à contenir uniquement CarAxle. En outre, vous ne pouvez pas diffuser une liste <Axle> dans la liste <CarAxle> - même s'il existe une chaîne d'héritage. Vous devez placer chaque objet dans une nouvelle liste (bien que cela devienne beaucoup plus facile avec LINQ).

Je prendrais des génériques moi-même.

0

J'ai demandé un similar question et j'ai eu une meilleure réponse, le problème est lié au support de C# pour la covariance et la contravariance. Voir cette discussion pour un peu plus d'informations.