2008-08-27 13 views
2

Ich versuche, eine Vererbungshierarchie ähnlich den folgenden einzurichten:Was ist die beste Methode, um ein Array zu erben, das für die Unterklasse spezifische Daten speichern muss?

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

ich in einem Motorrad-Objekt Achsen-Array und CarAxle Objekte in einem Auto-Objekt Achsen-Array nur speichern MotorcycleAxle Objekte möchte. Das Problem besteht darin, dass es keine Möglichkeit gibt, das Array in der Unterklasse zu überschreiben, um das eine oder das andere zu erzwingen. Im Idealfall würde so etwas wie die folgenden für die Motorrad-Klasse gilt:

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

aber die Typen müssen übereinstimmen, wenn überschreiben. Wie kann ich diese Architektur unterstützen? Muss ich einfach eine Vielzahl von Laufzeit-Typprüfungen und Castings durchführen, wo immer das Axles-Mitglied aufgerufen wird? Ich mag es nicht, Laufzeittypprüfungen hinzuzufügen, weil Sie beginnen, die Vorteile von starker Typisierung und Polymorphismus zu verlieren. In diesem Szenario müssen zumindest einige Laufzeitüberprüfungen durchgeführt werden, da die Eigenschaften WheelAttached und Left/RightWheelAttached vom Typ abhängen, ich möchte sie jedoch minimieren.

Antwort

5

Verwendung mehr Generika

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 Optionen in den Sinn. 1 wird unter Verwendung von Generika:

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

Die zweite Shadowing verwendet - und dies setzt voraus, Sie haben Eigenschaften:

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> 

Das Problem mit Shadowing ist, dass Sie eine generische Liste haben. Leider können Sie die Liste nicht so beschränken, dass sie nur CarAxle enthält. Sie können auch keine Liste <Achse> in die Liste <CarAxle> übertragen, obwohl dort eine Vererbungskette vorhanden ist. Sie müssen jedes Objekt in eine neue Liste umwandeln (obwohl das mit LINQ viel einfacher wird).

Ich würde selbst für Generika gehen.

0

Ich fragte eine similar question und bekam eine bessere Antwort, das Problem hängt mit C# 's Unterstützung für Kovarianz und Kontravarianz zusammen. Sehen Sie diese Diskussion für ein wenig mehr Informationen.