बस यह सुनिश्चित करने के लिए कि हम एक ही पृष्ठ पर हैं, विधि "छिपाना" तब है जब एक व्युत्पन्न वर्ग आधार वर्ग में एक ही नाम के एक सदस्य को परिभाषित करता है (जो कि, यदि यह एक विधि / संपत्ति है, तो आभासी / अति-योग्य नहीं है ), और "व्युत्पन्न संदर्भ" में व्युत्पन्न वर्ग के एक उदाहरण से आह्वान किए जाने पर, व्युत्पन्न सदस्य का उपयोग किया जाता है, जबकि यदि इसके आधार वर्ग के संदर्भ में एक ही उदाहरण द्वारा आह्वान किया जाता है, तो आधार वर्ग के सदस्य का उपयोग किया जाता है। यह सदस्य एब्सट्रैक्शन / ओवरराइडिंग से अलग है जहां बेस क्लास सदस्य एक प्रतिस्थापन को परिभाषित करने के लिए व्युत्पन्न वर्ग की उम्मीद करता है, और गुंजाइश / दृश्यता संशोधक से जो वांछित दायरे से बाहर के उपभोक्ताओं से एक सदस्य को "छिपाना" करता है।
इसकी अनुमति देने का संक्षिप्त उत्तर यह है कि ऐसा न करना डेवलपर्स को ऑब्जेक्ट-ओरिएंटेड डिज़ाइन के कई प्रमुख सिद्धांतों का उल्लंघन करने के लिए मजबूर करेगा।
यहाँ लंबा जवाब है; पहले, एक वैकल्पिक ब्रह्मांड में निम्न वर्ग संरचना पर विचार करें जहां C # सदस्य को छिपाने की अनुमति नहीं देता है:
public interface IFoo
{
string MyFooString {get;}
int FooMethod();
}
public class Foo:IFoo
{
public string MyFooString {get{return "Foo";}}
public int FooMethod() {//incredibly useful code here};
}
public class Bar:Foo
{
//public new string MyFooString {get{return "Bar";}}
}
हम बार में सदस्य को असहज करना चाहते हैं, और ऐसा करके बार को एक अलग MyFooString प्रदान करने की अनुमति देते हैं। हालाँकि, हम ऐसा नहीं कर सकते क्योंकि यह सदस्य छिपने पर वैकल्पिक-वास्तविकता निषेध का उल्लंघन करेगा। यह विशेष रूप से कीड़े के लिए व्याप्त होगा और इस बात का एक प्रमुख उदाहरण है कि आप इसे प्रतिबंधित क्यों करना चाहते हैं; उदाहरण के लिए, यदि आपने निम्नलिखित कार्य किया तो आपको कौन सा कंसोल आउटपुट मिलेगा?
Bar myBar = new Bar();
Foo myFoo = myBar;
IFoo myIFoo = myFoo;
Console.WriteLine(myFoo.MyFooString);
Console.WriteLine(myBar.MyFooString);
Console.WriteLine(myIFoo.MyFooString);
मेरे सिर के ऊपर से, मुझे वास्तव में यकीन नहीं है कि आपको उस अंतिम पंक्ति पर "फू" या "बार" मिलेगा। आप निश्चित रूप से पहली पंक्ति के लिए "फू" और दूसरे के लिए "बार" प्राप्त करेंगे, हालांकि सभी तीन चर बिल्कुल एक ही राज्य के साथ एक ही उदाहरण का संदर्भ देते हैं।
तो, भाषा के डिजाइनर, हमारे वैकल्पिक ब्रह्मांड में, संपत्ति छिपाने को रोककर इस स्पष्ट रूप से बुरे कोड को हतोत्साहित करते हैं। अब, कोडर के रूप में आपको वास्तव में ऐसा करने की आवश्यकता है। आप सीमा के आसपास कैसे पहुँचते हैं? खैर, बार की संपत्ति को अलग तरीके से नाम देने का एक तरीका है:
public class Bar:Foo
{
public string MyBarString {get{return "Bar";}}
}
पूरी तरह से कानूनी, लेकिन यह वह व्यवहार नहीं है जो हम चाहते हैं। बार का एक उदाहरण हमेशा MyFooString संपत्ति के लिए "फू" का उत्पादन करेगा, जब हम चाहते थे कि यह "बार" का उत्पादन करे। न केवल हमें यह जानना होगा कि हमारा IFoo विशेष रूप से एक बार है, हमें अलग-अलग एक्सेसर का उपयोग करने के लिए भी जानना होगा।
हम भी, काफी प्रशंसनीय, माता-पिता के बच्चे के रिश्ते को भूल सकते हैं और सीधे इंटरफ़ेस को लागू कर सकते हैं:
public class Bar:IFoo
{
public string MyFooString {get{return "Bar";}}
public int FooMethod() {...}
}
इस सरल उदाहरण के लिए, यह एक सटीक उत्तर है, जब तक कि आप केवल यह ध्यान रखते हैं कि फू और बार दोनों IFoos हैं। उपयोग कोड कुछ उदाहरणों को संकलित करने में विफल होगा क्योंकि एक बार एक फू नहीं है और इसे इस तरह से नहीं सौंपा जा सकता है। हालाँकि, अगर Foo के पास कुछ उपयोगी विधि "FooMethod" थी, जिसे बार की आवश्यकता थी, तो अब आप उस विधि को इनहेरिट नहीं कर सकते हैं; आपको या तो इसके कोड को बार में क्लोन करना होगा, या क्रिएटिव करना होगा:
public class Bar:IFoo
{
public string MyFooString {get{return "Bar";}}
private readonly theFoo = new Foo();
public int FooMethod(){return theFoo.FooMethod();}
}
यह एक स्पष्ट हैक है, और जबकि ओओ भाषा के कुछ कार्यान्वयन इसकी तुलना में थोड़ी अधिक राशि की कल्पना करते हैं, अवधारणात्मक रूप से यह गलत है; अगर बार जरूरत के उपभोक्ताओं फू की कार्यक्षमता को बेनकाब करने, बार चाहिए होना एक फू, नहीं है एक फू।
जाहिर है, अगर हमने फू को नियंत्रित किया, तो हम इसे आभासी बना सकते हैं, फिर इसे ओवरराइड कर सकते हैं। यह हमारे वर्तमान ब्रह्मांड में वैचारिक सर्वोत्तम अभ्यास है जब एक सदस्य को ओवरराइड होने की उम्मीद होती है, और वह किसी भी वैकल्पिक ब्रह्मांड में पकड़ बनाएगा जो छिपने की अनुमति नहीं देता है:
public class Foo:IFoo
{
public virtual string MyFooString {get{return "Foo";}}
//...
}
public class Bar:Foo
{
public override string MyFooString {get{return "Bar";}}
}
इसके साथ समस्या यह है कि वर्चुअल मेंबर एक्सेस, हुड के तहत, प्रदर्शन करने के लिए अपेक्षाकृत अधिक महंगा है, और इसलिए आप आमतौर पर केवल तब करना चाहते हैं जब आपको इसकी आवश्यकता होती है। हालांकि, छिपने की कमी आपको उन सदस्यों के बारे में निराशावादी होने के लिए मजबूर करती है जो एक अन्य कोडर जो आपके स्रोत कोड को नियंत्रित नहीं करता है, वह पुन: लागू करना चाह सकता है; किसी भी गैर-सीलबंद वर्ग के लिए "सबसे अच्छा अभ्यास" सब कुछ आभासी बनाने के लिए होगा जब तक कि आप विशेष रूप से इसे नहीं चाहते। यह अभी भी आपको छिपाने का सटीक व्यवहार नहीं देता है; यदि स्ट्रिंग एक बार है तो स्ट्रिंग हमेशा "बार" होगी। कभी-कभी यह अंतर्निहित स्थिति के स्तर के आधार पर, छिपे हुए राज्य डेटा की परतों का लाभ उठाने के लिए वास्तव में उपयोगी होता है, जिस पर आप काम कर रहे हैं।
सारांश में, सदस्य को छिपाना अनुमति देना इन बुराइयों का कम है। ऐसा नहीं होने से आम तौर पर ऑब्जेक्ट-ओरिएंटेड सिद्धांतों के खिलाफ होने वाले बदतर अत्याचारों को बढ़ावा दिया जा सकता है।