ما هي أفضل طريقة لوراثة مصفوفة تحتاج إلى تخزين بيانات محددة لفئة فرعية؟

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

سؤال

أحاول إعداد تسلسل هرمي للميراث مشابه لما يلي:

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 في مصفوفة محاور كائن دراجة نارية، وكائنات CarAxle في مصفوفة محاور كائن سيارة.تكمن المشكلة في عدم وجود طريقة لتجاوز المصفوفة الموجودة في الفئة الفرعية لفرض واحدة أو أخرى.من الناحية المثالية، سيكون شيء مثل ما يلي صالحًا لفئة الدراجات النارية:

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

ولكن يجب أن تتطابق الأنواع عند التجاوز.كيف يمكنني دعم هذه البنية؟هل سيتعين عليّ فقط إجراء الكثير من عمليات التحقق من النوع في وقت التشغيل والإرسال أينما يتم الوصول إلى عضو Axles؟لا أحب إضافة عمليات التحقق من النوع أثناء التشغيل لأنك تبدأ في فقدان فوائد الكتابة القوية وتعدد الأشكال.يجب أن يكون هناك على الأقل بعض عمليات التحقق من وقت التشغيل في هذا السيناريو نظرًا لأن خصائص WheelAttached وLeft/RightWheelAttached تعتمد على النوع، ولكني أرغب في تقليلها.

هل كانت مفيدة؟

المحلول

استخدم المزيد من الأدوية العامة

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

نصائح أخرى

يتبادر إلى ذهنك خياران.1 يستخدم الأدوية العامة:

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

والثاني يستخدم التظليل - وهذا يفترض أن لديك خصائص:

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 فقط.أيضًا، لا يمكنك إرسال قائمة <Axle> إلى القائمة <CarAxle> - على الرغم من وجود سلسلة وراثة هناك.يجب عليك إرسال كل كائن إلى قائمة جديدة (على الرغم من أن ذلك يصبح أسهل بكثير مع LINQ).

سأختار الأدوية العامة بنفسي.

سألت أ سؤال مماثل وحصلت على إجابة أفضل، المشكلة تتعلق بدعم C# للتباين المشترك والتباين.انظر تلك المناقشة لمزيد من المعلومات.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top