سؤال

وكما بقدر أنا أعلم أنه ليس من الممكن القيام بما يلي في C # 2.0

public class Father
{
    public virtual Father SomePropertyName
    {
        get
        {
            return this;
        }
    }
}

public class Child : Father
{
    public override Child SomePropertyName
    {
        get
        {
            return this;
        }
    }
}

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

public new Child SomePropertyName

هل هناك أي حل في 2.0؟ ماذا عن خصائص أخرى في 3.5 لمعالجة هذه المسألة؟

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

المحلول

وهذا غير ممكن في أي لغة. NET بسبب مخاوف نوع السلامة. في لغات من نوع آمنة، يجب توفير تغاير القيم العودة، وcontravariance لمعلمات. خذ هذا الرمز:

class B {
    S Get();
    Set(S);
}
class D : B {
    T Get();
    Set(T);
}

لأساليب Get، التغاير يعني أن T يجب أن تكون إما S أو نوع مشتق من S. وإلا، إذا كان لديك مرجع إلى كائن من نوع D تخزينها في B مكتوب متغير، عندما كنت دعا B.Get() أنك لن تحصل على للتمثيل الكائن باعتباره S الظهر - كسر نظام نوع

لأساليب Set، contravariance يعني أن T يجب أن تكون إما S أو النوع الذي S مستمد من. وإلا، إذا كان لديك مرجع إلى كائن من نوع D تخزينها في B مكتوب متغير، عندما كنت دعا B.Set(X)، حيث كان X من نوع S ولكن ليس من نوع T، D::Set(T) سيحصل على كائن من نوع انها لا تتوقع.

في C #، كان هناك قرارا واعيا لعدم السماح بتغيير نوع عند الحمولة الزائدة خصائص، حتى عندما يكون لديهم واحد فقط من جالبة / الزوج واضعة، لأنه لولا ذلك سلوك غير متناسقة جدا (<م> "هل تعني، I يمكن تغيير نوع على واحد مع جالبة، ولكن ليست واحدة مع كل جالبة واضعة لماذا لا " -؟!؟ مجهول المناوب الكون عضو)

نصائح أخرى

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

public class Father
{
    public Father SomePropertyName
    {
        get {
            return SomePropertyImpl();
        }
    }
    protected virtual Father SomePropertyImpl()
    {
        // base-class version
    }
}

public class Child : Father
{
    public new Child SomePropertyName
    {
        get
        { // since we know our local SomePropertyImpl actually returns a Child
            return (Child)SomePropertyImpl();
        }
    }
    protected override Father SomePropertyImpl()
    {
        // do something different, might return a Child
        // but typed as Father for the return
    }
}

لا، ولكن يمكنك استخدام الأدوية في 2 و أعلاه:

public class MyClass<T> where T: Person
{
    public virtual T SomePropertyName
    {
        get
        {
            return  ...;
        }
    }
}

وثم الأب والطفل إصدارات عامة من نفس الفئة

ويكيبيديا :

<اقتباس فقرة>   

في لغة البرمجة C #، ودعم كل من العائد من نوع   التغاير والمعلمة   تمت إضافة contravariance للمندوبين   في الإصدار 2.0 من لغة.   لا التغاير ولا contravariance   معتمدة لطريقة الغلابة.

وانه لا يقول صراحة أي شيء عن التغاير العقارات بالرغم من ذلك.

يمكنك إنشاء واجهة المشتركة للأب والطفل والعودة نوع من تلك الواجهة.

ولا. C # لا يدعم هذه الفكرة (انه دعا "نوع الإرجاع التغاير"). ولكن يمكنك القيام بذلك:

public class FatherProp
{
}

public class ChildProp: FatherProp
{
}


public class Father
{
    public virtual FatherProp SomePropertyName
    {
        get
        {
            return new FatherProp();
        }
    }
}


public class Child : Father
{
    public override FatherProp SomePropertyName
    {
        get
        {
            // override to return a derived type instead
            return new ChildProp();
        }
    }
}

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

ومن الممكن (ولكن الفوضى) لاختبار الكائن عاد لانها نوع الفعلية (أي "إذا someObject هو ChildProp")، ولكن من الأفضل أن استدعاء أسلوب الظاهري على أن يفعل الشيء الصحيح بالنسبة نوعه.

والأسلوب الظاهري الفئة الأساسية (في هذه الحالة، الملكية الظاهري) لديه التنفيذ فحسب، بل أيضا يحدد العقد: أن فئة الأطفال يمكن أن العرض تطبيق مختلف من SomePropertyName إذا استوفى هذا العقد (أي SomePropertyName بإرجاع كائن من نوع "FatherProp"). عودة كائن من نوع "ChildProp" مشتقة من "FatherProp" يجتمع هذا العقد. ولكن لا يمكنك تغيير العقد في "الطفل" - ينطبق هذا العقد لجميع فئات تنحدر من "الأب"

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

<اقتباس فقرة>   

ولا. C # لا يدعم هذه الفكرة   (انه دعا "نوع الإرجاع   التغاير ").

     

ومن ويكيبيديا:

     

في لغة C # البرمجة،   دعم كل عودة من نوع   التغاير والمعلمة   تمت إضافة contravariance للمندوبين   في الإصدار 2.0 من لغة.   لا التغاير ولا contravariance   معتمدة لطريقة الغلابة.

     

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

وأفضل الحلول سيكون لاستخدام الأدوية:

public class MyClass<T> where T: Person
{
   public virtual T SomePropertyNameA
   {        
      get { return  ...; }    
   }
}//Then the Father and Child are generic versions of the same class

وهذا هو الأقرب I يمكن أن تأتي (حتى الآن):

    public sealed class JustFather : Father<JustFather> {}

    public class Father<T> where T : Father<T>
    { public virtual T SomePropertyName
        { get { return (T) this; }
        }
    }

    public class Child : Father<Child>
    { public override Child SomePropertyName
        { get { return  this; }
        }
    }

وبدون الطبقة JustFather، هل يمكن أن لا مثيل Father<T> إلا إذا كان بعض المستمدة نوع آخر.

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