2010-01-19 16 views
8

कर्मचारी, प्रबंधक, और सहायक वर्गों पर विचार से एक प्रॉपर्टी को दबाने:नेट विरासत: आधार वर्ग

public class Emp 
{ 
    public string Name { get; set; } 
    public Manager Manager { get; set; } 
    public Assistant Assistant { get; set; } 
} 

public class Manager : Emp 
{ 
} 

public class Assistant : Emp 
{ 
} 

लक्ष्य इस तरह एक संपत्ति का उपयोग करने के कोड का एक टुकड़ा अस्वीकृत करने के लिए है:

Emp से
var foo = new Manager(); 
var elmo = new Emp(); 
elmo.Manager = foo; 
elmo.Manager.Manager = new Manager(); 
//how to disallow access to Manager.Manager ? 

क्योंकि Manager इनहेरिट करती है, यह एक .Manager और .Assistant संपत्ति है।

प्रश्न

वहाँ नेट के उत्तराधिकार कार्यान्वयन में किसी भी संशोधक .Manager और .Assistant गुण दूर करने के लिए कर रहे हैं?

अद्यतन

अपने महान जवाब, हर किसी के लिए धन्यवाद। मैं उम्मीद कर रहा था कि एएमपी/एमजीआर के सरलीकरण और प्रतिद्वंद्विता इस प्रश्न में दिखाई देगी। यह स्पष्ट है कि विरासत, इस उदाहरण में, एक और समानता के लिए (कुछ Person की तरह, आदि जहां कक्षाएं नाम, birthdates का हिस्सा होता है) से लिया जाना चाहिए आपका इनपुट बहुत सराहना कर रहा है!

+0

मुझे एक डिजाइन मुद्दे की तरह बदबू आ रही है। जबकि प्रबंधक किसी अन्य प्रबंधक को रिपोर्ट कर सकते हैं, सहायकों के पास शायद सहायक नहीं है। शायद आधार व्यक्ति होना चाहिए ... – Walter

उत्तर

9

ऐसा Liskov substitution principle का उल्लंघन होगा, और आमतौर पर एक संदिग्ध डिजाइन का एक संकेत है। आम तौर पर, किसी भी उप-वर्ग का उपयोग किसी भी संदर्भ में किया जा सकता है जिसे बेस क्लास होगा। Manager रों .Manager रों की जरूरत नहीं है, तो वे नहीं Emp रहे हैं, और उन लोगों से विरासत में नहीं करना चाहिए।

2

नहीं, नहीं है।

आप बेस क्लास प्रॉपर्टी virtual बना सकते हैं, फिर इसे सेटटर में अपवाद फेंकने के लिए ओवरराइड कर सकते हैं, लेकिन संकलन-समय त्रुटि देने का कोई तरीका नहीं है। सब के बाद, वहाँ

(elmo.Manager as Employee).Manager = new Manager(); 

हालांकि रोकने के लिए संकलन समय पर कुछ भी नहीं तुम क्या है, तो आप लिख सकते हैं

public class ManagerEmployee : Emp {  
    public new ManagerEmployee Manager { 
     get { return base.Manager; } 
    } 
} 

ध्यान दें कि यह कास्टिंग नहीं रोकेगा।

5

नहीं - क्योंकि यह Liskov's Subsitution Principle टूट जाएगा। असल में, आप चीजें जोड़ सकते हैं, लेकिन आप उन्हें दूर नहीं ले जा सकते हैं।

आप संभावित संपत्ति निष्पादन समय पर एक अपवाद फेंकने के लिए रद्द कर सकते थे, लेकिन आप संकलन समय पर यह नहीं कर सकते।

आम तौर पर अगर आप बात की इस तरह की अनुमति नहीं देने के लिए चाहते हैं, तो आप, विरासत रचना के बजाय विचार करना चाहिए जैसा कि आप एक वास्तविक विरासत संबंध नहीं है।

0

के रूप में अन्य लोगों ने कहा। नहीं। मैं जोड़ूंगा कि अगर प्रत्येक कर्मचारी के पास प्रबंधक और सहायक नहीं होता है, तो आपकी विरासत पदानुक्रम गलत है। ऐसा लगता है कि एकमात्र चीज एक कर्मचारी और प्रबंधक शेयर एक नाम है। आप विरासत के माध्यम से जोड़ सकते हैं, लेकिन आप दूर विरासत के माध्यम से नहीं ले सकते।

0

नहीं, आप यह नहीं कर सकते हैं, और आप नहीं चाहते हैं - या तो प्रबंधक एक कर्मचारी है और उसके पास एक प्रबंधक और सहायक है, या ऐसा नहीं है और इसलिए एक अलग आधार वर्ग होना चाहिए यानी यह स्थिति इंगित करती है एक डिजाइन दोष।इन गुणों के लिए शून्य वापस लौटने की संभावना हो सकती है, हालांकि यदि डोमेन के लिए यह समझ में आता है।

1

अधिकांश चीजों की तरह, यह निर्भर करता है।

public class foo 
{ 
    public string Test { get { return "foo"; } } 
} 

public class bar : foo 
{ 
    public new string Test { get { return "bar"; } } 
} 

और निम्नलिखित कोड: निम्नलिखित वर्गों को देखते हुए

 bar a = new bar(); 
     // returns bar 
     literalTest1.Text = a.Test; 

     foo b = new foo(); 
     // returns "foo" 
     literalTest2.Text = b.Test; 

     foo c = new bar(); 
     // returns "foo" 
     literalTest3.Text = c.Test; 

आप देख सकते हैं, ऊपर टिप्पणी के आधार पर, कि तुम एक संपत्ति है कि आभासी रूप में घोषित नहीं किया गया है ओवरराइड कर सकते हैं। हालांकि, ओवरराइड संपत्ति का उपयोग तब किया जाएगा जब ऑब्जेक्ट वैरिएबल को उस प्रकार के रूप में घोषित किया जाता है जो संपत्ति को ओवरराइड करता है - न कि उसके पूर्वजों के रूप में। यह प्रभावी ढंग से polymorphism तोड़ता है।

इसके बजाय अपने पूर्वजों वर्ग को ठीक करें।

संबंधित मुद्दे