سؤال

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

على سبيل المثال، إذا كانت الفئات الفرعية هي عقد DOM، وإذا كانت الخوارزمية هي إدراج عقدة تابعة، تختلف هذه الخوارزمية اعتمادا على ما إذا كانت العقدة الأصل عنصر دوم (يمكن أن يكون لديك أطفال) أو نص DOM (الذي لا يستطيع): و لذلك insertChildren قد تكون الطريقة افتراضية (أو مجردة) في DomNode الطبقة الأساسية، وتنفيذها بشكل مختلف في كل من DomElement و DomText الفئات الفرعية.

هناك احتمال آخر يعطي الحالات الممتلكات المشتركة، التي يمكن قراءة قيمتها: على سبيل المثال قد تقرأ الخوارزمية nodeType خاصية DomNode الطبقة الأساسية أو لمثال آخر، قد يكون لديك أنواع مختلفة (فرعية فرعية) من حزمة الشبكة، والتي تبادل رأس حزمة مشتركة، ويمكنك قراءة رأس الحزمة لمعرفة نوع الحزمة التي هو عليه.

لم أستخدم معلومات التشغيل من نوع التشغيل كثيرا، بما في ذلك:

  • ال is و as الكلمات الرئيسية في C #
  • Downcasting.
  • طريقة الكائن.
  • ال typeid المشغل في C ++

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

سؤالي هو، متى يكون من المناسب استخدام معلومات Run-Time-Type، بدلا من الوظائف الافتراضية؟

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

المحلول

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

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

نصائح أخرى

في C ++، من بين بعض الحالات الغامضة الأخرى (التي تتعامل معظمها مع خيارات التصميم السفلي)، RTTI هي وسيلة لتنفيذ ما يسمى طرق متعددة.

هذه المنشآت ("هي" و "AS") مألوفة للغاية لمطوري دلفي لأن معالجات الأحداث عادة ما تكون الأجسام في سلف مشترك. على سبيل المثال، يمر OnClick المرسل الوحيد: Tobject بغض النظر عن نوع الكائن، سواء كان tbutton، toListbox أو أي شيء آخر. إذا كنت ترغب في معرفة شيء ما حول هذا الكائن، عليك الوصول إليه من خلال "as"، ولكن من أجل تجنب استثناء، يمكنك التحقق من ذلك مع "هو" من قبل. يسمح هذا العجل بتجميل من نوع التصميم للكائنات والأساليب التي لا يمكن أن تكون ممكنة مع فحص نوع الفئة الصارمة. تخيل أنك تريد أن تفعل الشيء نفسه إذا النقر فوق المستخدم زر أو مربع القائمة، ولكن إذا واجهنا نماذج أولية مختلفة من الوظائف، فقد لا يمكن أن يكون من الممكن ربطها بنفس الإجراء.

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

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

ومع ذلك، لم أرها من النوع () في البرية في 10 سنوات من أعمال الصيانة المؤيدة C ++. (لحسن الحظ).

يمكنك الرجوع إلى C # فعالا للحصول على حالة عند التحقق من نوع وقت التشغيل على ما يرام.

البند 3. متخصص في الخوارزميات العامة باستخدام فحص نوع وقت التشغيل

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

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

على سبيل المثال، افترض أنك تكتب فئة توفر تعداد عكسي على تسلسل العناصر الممثلة من خلال iEnumperableu003CT> وبعد من أجل تعدادها للخلف، يمكنك تكرارها ونسخ العناصر إلى مجموعة متوسطة مع الوصول الفهرسي مثل قائمةu003CT> ومن تعداد تلك المجموعة باستخدام فهرس الوصول إلى الوراء. ولكن إذا كان IEnumerable الأصلي الخاص بك هو Ilist لماذا لا تستفيد منه وتوفير المزيد من طريقة الأداء (دون نسخ إلى المجموعة المتوسطة) لتكرر البنود إلى الوراء. لذلك هو أساسا هو خاص يمكننا الاستفادة منها ولكن لا تزال توفر نفس السلوك (تكرار التسلسل إلى الوراء).

ولكن بشكل عام، يجب أن تنظر بعناية في التحقق من نوع التشغيل والتأكد من أنه لا ينتهك مبدأ استبدال Liskov.

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