2

次のような継承階層を設定しようとしています。

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

MotorcycleAxle オブジェクトのみを Motorcycle オブジェクトの Axles 配列に格納し、CarAxle オブジェクトを Car オブジェクトの Axles 配列に格納したいと考えています。問題は、サブクラスの配列をオーバーライドしてどちらか一方を強制する方法がないことです。理想的には、Motorcycle クラスには次のようなものが有効です。

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

ただし、オーバーライドするときは型が一致する必要があります。このアーキテクチャをどのようにサポートできますか? Axles メンバーがアクセスされる場所で、多くの実行時の型チェックとキャストを行う必要があるだけですか? 実行時の型チェックを追加するのは好きではありません。強い型付けとポリモーフィズムの利点が失われ始めるからです。WheelAttached および Left/RightWheelAttached プロパティはタイプに依存するため、このシナリオでは少なくともいくつかの実行時チェックが必要ですが、それらを最小限に抑えたいと考えています。

4

3 に答える 3

5

より多くのジェネリックを使用する

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;
}
于 2008-08-27T20:10:28.373 に答える
0

私は同様の質問をし、より良い答えを得ました。問題は、共変性と反変性に対するC#のサポートに関連しています。詳細については、その説明を参照してください。

于 2008-09-05T22:21:41.823 に答える
0

2つのオプションが思い浮かびます。1はジェネリックを使用しています:

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

2番目はシャドウイングを使用します-これはあなたがプロパティを持っていることを前提としています:

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>

シャドウイングの問題は、一般的なリストがあることです。残念ながら、CarAxleのみを含むようにリストを制限することはできません。また、継承チェーンが存在する場合でも、List<Axle>をList<CarAxle>にキャストすることはできません。各オブジェクトを新しいリストにキャストする必要があります(ただし、LINQを使用するとはるかに簡単になります)。

私は自分でジェネリック医薬品を選びます。

于 2008-08-27T20:54:11.593 に答える