كيفية إجبار فئة مشتقة على تضمين خصائص معينة ذات قيمة افتراضية

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

سؤال

لدي هيكل صفي لتلعب الأدوار التي تبدو هكذا ...

public abstract class Item
{
   public abstract string Name { get; set; }
}

public abstract class Armor : Item
{
   public override string Name { get; set; }
}

public class Helmet : Armor
{
   public override string Name { get; set; }
}

في الأساس ، أحاول فرض كل نوع مشتق لتشمل خاصية "الاسم". هل هذه هي أفضل طريقة للقيام بذلك؟ أعلم أنه يمكنني إزالة "الملخص" من item.name ثم إزالة خصائص "Overriden" "في الدروع والخوذة. إذا فعلت ذلك ، فإن الرمز يبدو أنظف قليلاً ، لكنني قد أنسى ضبط القاعدة. اسم في هذه الفئات المشتقة.

هل يمكن لأحد أن يساعدني في إظهار أفضل طريقة للقيام بذلك؟

تحرير: آسف ، دعني أوضح سؤالي أكثر قليلاً. أريد أن أتأكد من شيئين. 1) خاصية الاسم موجودة في جميع الفئات المشتقة 2) خاصية الاسم ليست فارغة أو فارغة

أريد أساسًا فرض أي فصل مستمد من العنصر (وليس مجردة) أن يكون له قيمة للاسم.

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

المحلول

يبدو أنك قلق بشأن تهيئة العقارات؟

لكنني قد أنسى ضبط القاعدة. الاسم في هذه الفصول المشتقة.

إحدى الطرق التي يمكنك بها فرض خاصية الاسم التي سيتم تعيينها هي تضمين هذا Setter في مُنشئ الفصل الأساسي مثل SO:

public class MyBaseClass
{
    private string _name;

    public MyBaseClass(string name)
    {
        _name = name;
    }
}

ثم يجب أن يرضي كل ما يستمد من MyBaseClass:

public class MyDerivedClass
{
    public MyDerivedClass(string name) : base(name)
    {

    }
}

ثم يمكنك أيضًا جعل العقار أيضًا:

  • مجردة لضمان وجودها في كل فئة مشتقة بتنفيذها الخاص
  • افتراضية لتوفير تنفيذ قاعدة وكل ما يجب تجاوزه.

لن أتحرك ما إذا كان ما سبق هو تصميم جيد ، لكن من شأنه أن يضمن أن جميع الفصول المشتقة لها خاصية اسم صالحة عند إنشاء مثيل لها.

هناك نهج آخر ، كما تشير الإجابات الأخرى ، وهو تنفيذ خاصية افتراضية يلقي استثناءً في تنفيذها الأساسي.

نصائح أخرى

تحتاج فقط إلى تحديد Name في الفئة الأساسية ، ولا تحتاج إلى تحديدها على أنها مجردة. سيظل متاحًا كعقار في جميع الفصول المشتقة.

public abstract class Item
{
   public string Name { get; set; }
}

public abstract class Armor : Item
{ }

public class Helmet : Armor
{ }

إذا فعلت ذلك ، فإن الرمز يبدو أنظف قليلاً ، لكنني قد أنسى ضبط القاعدة. اسم في هذه الفئات المشتقة.

ثم سينتهي اسم الكائن إلى أن يكون شيئًا سخيفًا.

الأفضل من ذلك ، لديك name ابدأ null. بعد ذلك ، ستحصل على استثناء إذا نسيت تهيئة الاسم ولكن شخص ما يحاول استخدامه ، وستعرف أنه يتعين عليك إصلاحه.

مايك محق في أنه إذا كنت ترغب فقط في استخدام "الاسم" الخاصية على جميع الكائنات المشتقة ، فلن تحتاج إلى وضع علامة تجريدية على الإطلاق كما هو ورث.

إذا كنت ترغب في إجبار حقيقة أنه عند إنشاء العناصر ، يتم تعيين اسم بالتأكيد ، فيمكنك إجباره من خلال إخفاء مُنشئ المعلمة الصفرية وفضح مُنشئ يقبل الاسم.

ألق نظرة على هذا الرمز:

public class Item
{
   public string Name { get; set; }

   public Item(string name)
   {
       this.Name = name;
   }

   protected Item() {}
}

public class Armor : Item
{   
   public Armor(string name) : base(name) {}
   protected Armor() {}
}

public class Helmet : Armor
{   
   public Helmet(string name) : base(name) {}
   protected Helmet() {}
}

التعريفات المذكورة أعلاه تعني أن:

Helmet myHelmet = new Helmet(); //will not build
Helmet myHelmet = new Helmet("Some Fancy Helmet Name"); //will build

Armor myArmor  = new Armor (); //will not build
Armor myArmor  = new Armor ("Some Fancy Armor Name"); //will build

Item myItem = new Item (); //will not build
Item myItem = new Item("Some Fancy Item Name"); //will build

هذا يجبر أي مثيل من الفئات على تحديد الاسم في وقت الخلق. حل واحد ممكن على أي حال ...

سوف تجعل الاسم ظاهري IE. public virtual Name {get; set; } يمكن استخدام الملحق في فئة العنصر؟ منذ هيلمنت ودرع ينزل من فئة العنصر. من شأنه أن ينفذ أنه يجب تجاوزها ...

أتمنى أن يساعد هذا ، مع أطيب التحيات ، توم.

لذلك يعتمد على ما تريد القيام به ...

إن جعل الفصل التجريدي يفرض جميع الفئات الفرعية لتنفيذ الفصل (ووظائفه التجريدية ، وما إلى ذلك) ، ولكن إذا كنت تريد أن يكون للدالة وظيفة أساسية مع إمكانية تجاوز الوظيفة ، فسأقترح عدم صنع الفصل مجردة وجعل الوظيفة المحددة افتراضية بدلاً من ذلك ، وبالتالي عندما لا يتم كتابة الوظيفة الافتراضية ، وسيتم استدعاء الوظيفة الأساسية.

وهناك دائمًا خيارات لإنشاء خصائص "جديدة" بنفس الاسم ، لكنني لا أعتقد أن هذه ممارسة جيدة.

امل ان يساعد.

أعتقد أنه لا يزال بإمكانك جعل العقار افتراضيًا ضمن فئة مجردة ، وبالتالي يجب أن يحل مشكلتك.

يمكنك تعيين القيمة على شيء محدد في الفئة التجريدية الأساسية ، هنا مثال:

public abstract class Item
{
   public virtual string Name 
   { 
         get {return m_strName;} 
         set {m_strName = value;}
   }

public abstract class Armor : Item
{
   public override string Name { get; set; } // if you want to override it 
}

public class Helmet : Armor
{
   public override string Name { get; set; } // if you want to override it
}
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top