سؤال

انتاج:
ب-> مرحبا! من صريحة.

لا ينبغي أن يكون:؟
أ-> مرحبا! من صريحة.

لماذا لا تصمم المدلى به (Ihello) دعوة Ihello.hello () من الفصل أ؟

interface IHello
{
    void Hello();
}

class A : IHello
{

    public virtual void Hello()
    {
        Console.WriteLine("A->Hello!");
    }

    void IHello.Hello()
    {
        Console.WriteLine("A->Hello! from Explicit.");
    }
}

class B : A, IHello
{
    public override void Hello()
    {
        Console.WriteLine("B->Hello!");
    }

    void IHello.Hello()
    {
        Console.WriteLine("B->Hello! from Explicit.");
    }
}

class Program
{
    static void Main(string[] args)
    {
        A a = new B();
        ((IHello)a).Hello();
    }
}
هل كانت مفيدة؟

المحلول

لا، لا ينبغي ذلك.

دعوة إلى Hello أي ما يعادل واحد التعليق - الطريق للحصول على IHello لا يهم (ما لم يتطلب فحص وقت التنفيذ أو التحويل)؛ نوع الترجمة هو فقط IHello في كلتا الحالتين، ورسم خرائط الواجهة هو نفسه ولكنك تصل إلى هناك.

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

من القسم 13.4.4 من المواصفات C # 3.0:

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

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

نصائح أخرى

(أ) لا يفعل شيئا. تم الإعلان عن المرجع بالفعل كإشارة إلى أنه لن يكون له أي تأثير.

على الرغم من أن المرجع الخاص بك يتم الإعلان عن، فإن الكائن الذي يشير إليه هو من النوع B. إذا قمت بإلقاء هذا الكائن على Ihello، فإن مكالمة إلى Hello () ستسمح بتنفيذ كائن B الصريح لل hello.

الناتج هو بالضبط كما هو متوقع.

لا، عند إنشاء الجديد الطريقة (ToString)، ليس الظاهري. جديد فقط يعني أنك لا تمانع في "إخفاء" الإصدار في الفئة الأساسية - لذلك إذا قمت بالاتصال به مرجع تمتلكه إلى نوع معين (أ)، فإنه ينفذ الطريقة في الفصل أ، بغض النظر عن النوع الفعلي للكائن الذي تتصل به. (أي كنت تسمى A.Tostring () لذلك تنفذ A.Tostring ())

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

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

لا، لا ينبغي ذلك.

عند استدعاء طريقة افتراضية، لا يهم ما هو نوع المرجع. يتم تحديد الطريقة التي يتم استدعاؤها بواسطة النوع الفعلي للكائن، وليس نوع المرجع.

كما يمكنك إنشاء مثيل للفئة B, ، النوع الفعلي للكائن هو B. وبعد السبب في أن يطبع "This is class A." هو أنك لم تغادر ToString طريقة في الفصل B, ، لقد غلبت ذلك باستخدام new الكلمة الرئيسية. لذلك B الطبقة لديها اثنين ToString الأساليب، واحد موروثة من الفصل A والآخر الذي يظليله. إذا كنت تستخدم A إشارة للاتصال ToString الطريقة، يتم استدعاء الطريقة الموروثة، ولكن إذا كنت قد استخدمت أ B إشارة إلى الاتصال به، وسيتم استدعاء طريقة التظليل، والطباعة "This is class B.".

أيضا إذا تجاوزت ToString طريقة في الفصل B بدلا من التظليل، سطبع "This is class B." بغض النظر عن نوع المرجع.

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