निम्नलिखित कई अन्य उत्तरों के सर्वोत्तम पहलुओं के साथ-साथ आवश्यक प्रकार की संपत्ति Cat
होने के प्रमुख पहलू को अनुमति देने के लिए एक तकनीक को जोड़ती है , लेकिन वापस लौटने में सक्षम होने के नाते जैसे कि हम केवल जानते हैं कि हमें इसके बजाय मिला है विशेष रूप से एExcrement
RadioactivePoo
Poo
AnimalBase
Cat
।
कॉलर्स को जेनेरिक का उपयोग करने की आवश्यकता नहीं होती है, भले ही वे कार्यान्वयन में मौजूद हों, और न ही विशेष प्राप्त करने के लिए एक अलग नाम वाले फ़ंक्शन को कॉल करने के लिए Poo
।
मध्यवर्ती वर्ग AnimalWithSpecialisations
केवल Excrement
संपत्ति को सील करने के लिए कार्य करता है, इसे गैर-सार्वजनिक SpecialPoo
संपत्ति के माध्यम से व्युत्पन्न वर्ग से जोड़ता है AnimalWithSpecialPoo<TPoo>
जिसमें Excrement
एक व्युत्पन्न रिटर्न प्रकार की संपत्ति होती है।
यदि Cat
एकमात्र ऐसा जानवर Poo
है, जो किसी भी तरह से विशेष है, या हम नहीं चाहते हैं कि किस प्रकार की Excrement
मुख्य परिभाषित विशेषता हो Cat
, मध्यवर्ती सामान्य वर्ग को पदानुक्रम में छोड़ दिया जा सकता है, तो यह Cat
सीधे से प्राप्त होता है AnimalWithSpecialisations
, लेकिन अगर वहाँ कई अलग-अलग जानवर हैं, जिनकी प्राथमिक विशेषता यह है कि उनकी Poo
किसी न किसी तरह से विशेष है, "बॉयलरप्लेट" को मध्यवर्ती कक्षाओं में अलग करना, Cat
अतिरिक्त आभासी फ़ंक्शन कॉल के एक जोड़े की कीमत पर वर्ग को खुद को काफी साफ रखने में मदद करता है ।
उदाहरण कोड दिखाता है कि अधिकांश अपेक्षित संचालन "अपेक्षा के अनुरूप" काम करते हैं।
public interface IExcretePoo<out TPoo>
where TPoo : Poo
{
TPoo Excrement { get; }
}
public class Poo
{ }
public class RadioactivePoo : Poo
{ }
public class AnimalBase : IExcretePoo<Poo>
{
public virtual Poo Excrement { get { return new Poo(); } }
}
public class Dog : AnimalBase
{
}
public abstract class AnimalWithSpecialisations : AnimalBase
{
public sealed override Poo Excrement { get { return SpecialPoo; } }
protected virtual Poo SpecialPoo { get { return base.Excrement; } }
}
public abstract class AnimalWithSpecialPoo<TPoo> : AnimalWithSpecialisations, IExcretePoo<TPoo>
where TPoo : Poo
{
sealed protected override Poo SpecialPoo { get { return Excrement; } }
public new abstract TPoo Excrement { get; }
}
public class Cat : AnimalWithSpecialPoo<RadioactivePoo>
{
public override RadioactivePoo Excrement { get { return new RadioactivePoo(); } }
}
class Program
{
static void Main(string[] args)
{
Dog dog = new Dog();
Poo dogPoo = dog.Excrement;
Cat cat = new Cat();
RadioactivePoo catPoo = cat.Excrement;
AnimalBase animal = cat;
Poo animalPoo = catPoo;
animalPoo = animal.Excrement;
AnimalWithSpecialPoo<RadioactivePoo> radioactivePooingAnimal = cat;
RadioactivePoo radioactivePoo = radioactivePooingAnimal.Excrement;
IExcretePoo<Poo> pooExcreter = cat;
IExcretePoo<RadioactivePoo> radioactivePooExcreter = cat;
animal = dog;
animalPoo = dogPoo;
pooExcreter = dog;
}