سؤال

دعونا نقول لدينا ملموسة class Apple.(أبل الكائنات يمكن إنشاء مثيل.) الآن يأتي شخص و تستمد مجردة class Peach من شركة أبل.انها مجردة لأنه يقدم الجديد نقي الظاهري وظيفة.المستخدم من الخوخ يضطر الآن إلى تستمد من تحديد هذه الوظيفة الجديدة.هل هذا شائع النمط ؟ هل هذا صحيح أن تفعل ؟

العينة:


class Apple
{
public:
    virtual void MakePie();
    // more stuff here
};

class Peach : public Apple { public: virtual void MakeDeliciousDesserts() = 0; // more stuff here };

الآن دعونا نقول لدينا ملموسة class Berry.شخص يستمد مجردة class Tomato من التوت.انها مجردة لأن الكتابة واحدة من بيري وظائف افتراضية, ويجعلها نقية الظاهري.المستخدم من الطماطم إلى إعادة تنفيذ المهمة المحددة سابقا في التوت.هل هذا شائع النمط ؟ هل هذا صحيح أن تفعل ؟

العينة:


class Berry
{
public:
    virtual void EatYummyPie();
    // more stuff here
};

class Tomato : public Berry { public: virtual void EatYummyPie() = 0; // more stuff here };

ملاحظة:الأسماء هي مفتعلة ولا تعكس أي رمز الفعلي (أمل).لا الفواكه تضرروا في كتابة هذا السؤال.

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

المحلول

إعادة الخوخ من أبل:

  • لا تفعل ذلك إذا كان التفاح هو قيمة الدرجة (أيوقد نسخ المنشئ غير متطابقة الحالات يمكن أن تكون على قدم المساواة ، إلخ).انظر مايرز أكثر فعالية C++ البند 33 لماذا.
  • لا تفعل ذلك إذا أبل لديها العامة nonvirtual المدمر ، وإلا كنت دعوة غير معروف السلوك عندما الخاص بك المستخدمين حذف تفاحة من خلال مؤشر إلى الخوخ.
  • وإلا ربما كنت آمنة, لأنك لم تنتهك Liskov الاستبدال.الخوخ هو أبل.
  • إذا كنت تملك أبل رمز يفضلون عامل مشترك مجردة الفئة الأساسية (الفاكهة ربما) و تستمد التفاح و الخوخ من ذلك.

إعادة الطماطم من التوت:

  • نفس أعلاه, بالإضافة إلى:
  • تجنب لأنه غير عادية
  • إذا كان يجب أن الوثيقة ما الفئات المشتقة من الطماطم يجب أن نفعل لكي لا تنتهك Liskov الاستبدالية.وظيفة أنت المهيمن في بيري - دعنا نسميها Juice() - يفرض بعض الشروط و يجعل بعض الوعود.الفئات المشتقة' تطبيقات Juice() يجب أن لا تحتاج إلى أكثر الوعد ولا أقل.ثم DerivedTomato هو-التوت و القانون الذي لا يعرف سوى التوت آمنة.

ربما سوف يجتمع الشرط الأخير من خلال توثيق هذا DerivedTomatoes يجب استدعاء Berry::Juice().إذا كان الأمر كذلك, النظر في استخدام طريقة القالب بدلا من ذلك:

class Tomato : public Berry
{
public:
    void Juice() 
    {
        PrepareJuice();
        Berry::Juice();
    }
    virtual void PrepareJuice() = 0;
};

الآن هناك فرصة ممتازة أن الطماطم هي-التوت ، على عكس النباتية التوقعات.(والاستثناء الوحيد هو إذا الفئات المشتقة' تطبيقات PrepareJuice فرض شروط مسبقة إضافية تتجاوز تلك التي تفرضها Berry::Juice).

نصائح أخرى

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

نعم، وأكثر أفكر في ذلك، وهذا هو فكرة سيئة للغاية.

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

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

وتحرير: إعادة قراءة وأرى أن هذه نوعان من التسلسلات الهرمية. كل الاشياء الفاكهة حصلت لي الخلط.

إذا كنت تستخدم الممارسة الموصى بها من وجود نموذج الميراث "هو-" ثم هذا النمط سيكون الى حد كبير لا تأتي أبدا.

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

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

هذا هو المكان الذي عادة ما ينصح الاحتواء, لكن هذا لا يبدو أن يكون نموذجا جيدا منذ التفاح لا يحتوي الخوخ.

في هذه الحالة أريد أن عامل واجهة مشتركة -- PieFilling أو DessertItem.

وغير عادي بعض الشيء، ولكن إذا كان لديك بعض فرعية أخرى من الفئة الأساسية وكان فرعية من فئة مجردة الاشياء المشتركة بما فيه الكفاية لتبرير الوجود من فئة مجردة مثل:

class Concrete
{
public:
    virtual void eat() {}
};
class Sub::public Concrete { // some concrete subclass
    virtual void eat() {}
};
class Abstract:public Concrete // abstract subclass
{
public:
    virtual void eat()=0;
    // and some stuff common to Sub1 and Sub2
};
class Sub1:public Abstract {
    void eat() {}
};
class Sub2:public Abstract {
    void eat() {}
};
int main() {
    Concrete *sub1=new Sub1(),*sub2=new Sub2();
    sub1->eat();
    sub2->eat();
    return 0;
}

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

ووالكثير من القرف غريب يمكنك القيام به في C ++ ... لا أستطيع أن أفكر حتى 1٪ من ذلك ...

وعن تجاوز ظاهري مع نقية الظاهري، وربما يمكنك فقط إخفائه وسيكون غريب حقا ...

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

وأعتقد أن هذا يمكن أن يتم إلا عن الإختراق وليس لدي أي فكرة عن أي نوع من الإختراق حقا ...

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

لا أستطيع أن أتخيل بعد مدى فائدة سيكون لتجاوز دالة ظاهري مع نقية الظاهري واحد - هو أنه حتى القانونية

في عام تريد أن تتفق مع سكوت مايرز "جعل جميع الطبقات غير طرفية مجردة" عنصر من كتبه.

وعلى أي حال، وبصرف النظر عن أن ما تصفون يبدو أن تكون قانونية - لمجرد أنني لا أستطيع أن أراك في حاجة لها في كثير من الأحيان

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