2009-11-25 15 views
8

ठीक है, चलो कहते हैं कि हम एक वर्गप्रतिबिंब सिद्धांत encapsulation सिद्धांत तोड़ रहा है?

public class TestClass 
{ 
    private string MyPrivateProperty { get; set; } 

    // This is for testing purposes 
    public string GetMyProperty() 
    { 
     return MyPrivateProperty; 
    } 
} 

तरह परिभाषित किया है चलो फिर हम कोशिश: के रूप में उम्मीद

TestClass t = new TestClass { MyPrivateProperty = "test" }; 

संकलन, TestClass.MyPrivateProperty is inaccessible due to its protection level साथ विफल रहता है।

TestClass t = new TestClass(); 
t.MyPrivateProperty = "test"; 

की कोशिश करो और संकलन फिर विफल रहता है, एक ही संदेश के साथ।

अब तक सभी अच्छे, हम इसकी अपेक्षा कर रहे थे।

लेकिन फिर एक लिखने:

PropertyInfo aProp = t.GetType().GetProperty(
     "MyPrivateProperty", 
     BindingFlags.NonPublic | BindingFlags.Instance); 

// This works: 
aProp.SetValue(t, "test", null); 

// Check 
Console.WriteLine(t.GetMyProperty()); 

और यहाँ हम कर रहे हैं, हम एक निजी क्षेत्र को बदलने में कामयाब रहे।

क्या यह किसी असामान्य नहीं है कि प्रतिबिंब का उपयोग करके किसी ऑब्जेक्ट की आंतरिक स्थिति को बदलने में सक्षम हो?

संपादित करें:

उत्तरों अब तक के लिए धन्यवाद। उन लोगों के लिए "आपको इसका उपयोग नहीं करना है": क्लास डिजाइनर के बारे में क्या, ऐसा लगता है कि वह अब आंतरिक राज्य सुरक्षा नहीं ले सकता है?

+0

बस प्रतिबिंब का उपयोग करके? कोई प्रतिबिंब का उपयोग नहीं करता है, एक बिल्कुल जानता है कि वह एपीआई तोड़ रहा है। –

उत्तर

13

प्रतिबिंब निजी क्षेत्रों और विधियों तक पहुंच प्रदान करके encapsulation सिद्धांतों को तोड़ता है, लेकिन यह पहला या एकमात्र तरीका नहीं है जिसमें encapsulation को रोका जा सकता है; कोई तर्क दे सकता है कि धारावाहिकता कक्षा के सभी आंतरिक डेटा को उजागर करती है, जो जानकारी सामान्य रूप से निजी होगी।

यह समझना महत्वपूर्ण है कि encapsulation केवल एक तकनीक है, जो डिजाइनिंग व्यवहार को आसान बनाता है, बशर्ते उपभोक्ता आपके द्वारा परिभाषित एपीआई का उपयोग करने के लिए सहमत हों। अगर कोई प्रतिबिंब या किसी अन्य तकनीक का उपयोग करके आपके एपीआई को बाधित करने का विकल्प चुनता है, तो अब उन्हें यह आश्वासन नहीं है कि आपका ऑब्जेक्ट व्यवहार करेगा जैसा आपने इसे डिज़ाइन किया था। अगर कोई निजी क्षेत्र में null का मान निर्दिष्ट करता है, तो अगली बार जब वे आपकी कक्षा का उपयोग करने का प्रयास करेंगे तो वे NullReferenceException पकड़ने के लिए तैयार होंगे!

मेरे अनुभव में, प्रोग्रामिंग सभी सम्मिलनों और धारणाओं के बारे में है। भाषा बाधाओं (कक्षाओं, इंटरफेस, गणना) पर जोर देती है जो इस बात पर निर्भर करती है कि एक उपभोक्ता उन सीमाओं का उल्लंघन नहीं करने के लिए सहमत है, अलग-अलग व्यवहार को उत्पन्न करना बहुत आसान बनाता है।

यह उचित दावा देने के लिए यह सॉफ्टवेयर विकास के लिए एक विभाजन और जीत दृष्टिकोण को इससे पहले किसी भी तकनीक से अधिक आसान बनाता है।

+1

हालांकि इस प्रश्न को अन्य उत्कृष्ट उत्तर प्राप्त हुए हैं, लेकिन इस तथ्य पर जोर देने के कारण मैं इसे रोक रहा हूं कि किसी को encapsulation कई अन्य लोगों के बीच एक (अनुशंसित) तकनीक के रूप में। –

8

प्रतिबिंब एक उपकरण है। आप इसे encapsulation तोड़ने के लिए उपयोग कर सकते हैं, जब यह आपको इससे अधिक दूर ले जाता है।

प्रतिबिंब में एक निश्चित "दर्द" (या प्रदर्शन में, प्रदर्शन में, कोड की विश्वसनीयता में, कोडकता की विश्वसनीयता में) है, इसलिए आप इसे एक सामान्य समस्या के लिए उपयोग नहीं करेंगे। सामान्य समस्याओं के लिए ऑब्जेक्ट उन्मुख सिद्धांतों का पालन करने के लिए यह आसान है, जो भाषा के लक्ष्यों में से एक है, जिसे आमतौर पर the pit of success कहा जाता है।

दूसरी तरफ, कुछ ऐसे कार्य हैं जो उस तंत्र के बिना हल नहीं होंगे, उदा। रन-टाइम जेनरेट प्रकारों के साथ काम करना (हालांकि, यह .NET 4.0 से इसके डीएलआर और सी # 4.0 में "गतिशील" चर के साथ शुरू करना बहुत आसान हो जाएगा।

2

कोई कह सकता है कि प्रतिबिंब विरासत और बहुरूपता को तोड़ देता है। जब प्रत्येक ऑब्जेक्ट प्रकार को अपने स्वयं के अधिभारित विधि संस्करण के साथ आपूर्ति करने की बजाय आपके पास एक ही विधि होती है जो ऑब्जेक्ट प्रकार को रन टाइम पर जांचती है और प्रत्येक के लिए किसी विशेष व्यवहार में स्विच करती है।

प्रतिबिंब फिर भी एक अच्छा उपकरण है। कभी-कभी आपको किसी ऑब्जेक्ट को एक निजी कन्स्ट्रक्टर के साथ चालू करने की आवश्यकता होती है क्योंकि यह क्रिया का इष्टतम तरीका है और आप कक्षा कार्यान्वयन (बंद पुस्तकालय, लेखक के संपर्क में नहीं रह सकते हैं) को बदल नहीं सकते हैं। या आप एक ही स्थान पर विभिन्न वस्तुओं पर कुछ सहायक संचालन करना चाहते हैं। या शायद आप कुछ प्रकार के लिए लॉगिंग करना चाहते हैं। ये स्थिति है जब प्रतिबिंब किसी भी नुकसान के बिना मदद करता है।

2

यह प्रतिबिंब द्वारा प्रदान की गई कार्यक्षमता का हिस्सा है, लेकिन नहीं, मैं कहूंगा, इसका सबसे अच्छा उपयोग।

यह केवल पूर्ण ट्रस्ट के तहत काम करता है।

3

मुझे लगता है कि आप यह कह सकते हैं। आप यह भी कह सकते हैं कि कोडडॉम, रिफ्लेक्शन एमिट, और एक्सप्रेशन ट्री एपीआई आपको फ्लाई पर कोड लिखने की अनुमति देकर encapsulation तोड़ते हैं। वे केवल .NET द्वारा प्रदान की जाने वाली सुविधाएं हैं। आपको उनका उपयोग करने की ज़रूरत नहीं है।

भूलें कि आपको (ए) पूर्ण विश्वास में चलना है, और (बी) निजी डेटा तक पहुंचने के लिए स्पष्ट रूप से BindingFlags.NonPublic निर्दिष्ट करें। यह एक सुरक्षा नेट के लिए पर्याप्त होना चाहिए।

2

नहीं, यह असामान्य नहीं है।
यह कुछ प्रतिबिंब आपको करने की अनुमति देता है, कुछ स्थितियों में आपने कुछ उपयोग किए हैं, कई अन्य लोगों में जो आपके कोड को एक समय बम बना देगा।

प्रतिबिंब एक उपकरण है, इसका उपयोग या दुरुपयोग किया जा सकता है।


आपके संपादन के बाद प्रश्न के बारे में: उत्तर बस नहीं है। एक एपीआई डिजाइनर अपना सर्वश्रेष्ठ प्रदर्शन कर सकता है, एक साफ इंटरफ़ेस को उजागर करने में बहुत प्रयास कर सकता है और प्रतिबिंब का उपयोग कर अपने एपीआई का अत्यधिक दुरुपयोग देख सकता है।

एक इंजीनियर एक परिपूर्ण वाशिंग मशीन मॉडल कर सकता है जो सुरक्षित है, आपको बिजली से झटका नहीं देता है, लेकिन यदि आप इसे तब तक हथौड़ा से तोड़ते हैं जब तक कि आप केबल नहीं देखते हैं, कोई भी इंजीनियर को दोष नहीं देगा यदि आप एक सदमे प्राप्त करें: डी

+0

हाहा, वाशिंग मशीन ... तो encapsulation एक वारंटी प्रमाण पत्र के साथ आता है, आप कह रहे हैं;)? –

+0

हेहे ... शायद एक अनुबंध के साथ: पी –

2

encapsulation सिद्धांत आपके एपीआई द्वारा धारण किया जाता है, लेकिन प्रतिबिंब आपको एपीआई के आसपास काम करने का एक तरीका देता है।

जो भी प्रतिबिंब का उपयोग करता है जानता है कि वह आपके एपीआई का सही ढंग से उपयोग नहीं कर रहा है!

+0

बहुत स्पष्ट और याद रखना आसान है:) ... –

1

प्रतिबिंब आपको अपना कोड साफ़ रखने में मदद कर सकता है। जैसे जब आप हाइबरनेट का उपयोग करते हैं तो आप सीधे डीबी मानों पर निजी चर को बाध्य कर सकते हैं और आपको अनावश्यक सेटर विधियों को लिखना नहीं है जिन्हें आपको अन्यथा आवश्यकता नहीं है। इस दृष्टिकोण से देखा गया, प्रतिबिंब आपको encapsulation रखने में मदद कर सकता है।

3

आप सही हैं कि प्रतिबिंब किसी भी अच्छे डिजाइन सिद्धांतों का विरोध कर सकता है, लेकिन यह एक आवश्यक बिल्डिंग ब्लॉक भी हो सकता है जिसका उपयोग आप अच्छे डिजाइन सिद्धांतों का समर्थन करने के लिए कर सकते हैं - उदा। सॉफ़्टवेयर जिसे प्लगइन, नियंत्रण में उलटा इत्यादि द्वारा बढ़ाया जा सकता है

यदि आप चिंतित हैं कि यह एक क्षमता का प्रतिनिधित्व करता है जिसे निराश किया जाना चाहिए, तो आपके पास एक बिंदु हो सकता है। लेकिन यह वास्तविक भाषा सुविधाओं के रूप में उपयोग करने के लिए सुविधाजनक नहीं है, इसलिए चीजों को सही तरीके से करना आसान है।

यदि आपको लगता है कि प्रतिबिंब असंभव होना चाहिए, तो आप सपने देख रहे हैं!

सी ++ में इस तरह कोई प्रतिबिंब नहीं है। लेकिन एक अंतर्निहित "ऑब्जेक्ट मॉडल" है कि संकलक-जेनरेट किया गया मशीन कोड ऑब्जेक्ट्स (और वर्चुअल फ़ंक्शंस) की संरचना तक पहुंचने के लिए उपयोग करता है। तो एक सी ++ प्रोग्रामर उसी तरह से encapsulation तोड़ सकता है।

class RealClass 
{ 
private: 
    int m_secret; 
}; 

class FakeClass 
{ 
public: 
    int m_notSecret; 
}; 

हम प्रकार RealClass का एक उद्देश्य के लिए सूचक ले जा सकते हैं और बस FakeClass करने के लिए इसे डाली और "निजी" सदस्य एक्सेस करते हैं।

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

कुछ भाषाओं में डेटा को समाहित करने के तरीके हैं ताकि भाषा में संभवतः कुछ निर्धारित तरीकों को छोड़कर डेटा प्राप्त करने के लिए संभव नहीं है। लेकिन अगर आप भाषा से बाहर निकलने का कोई रास्ता ढूंढ सकते हैं तो धोखा देना हमेशा संभव होगा। एक चरम उदाहरण जावास्क्रिप्ट में चर scoped जाएगी:

(function() { 

    var x = 5; 

    myGetter = function() { return x; }; 
    mySetter = function(v) { x = v; }; 

})(); 

कि कार्यान्वित करने के बाद, वैश्विक नामस्थान दो कार्यों, myGetter और mySetter, जो x का मूल्य तक पहुँचने के लिए एक ही रास्ता होते हैं। जावास्क्रिप्ट में x किसी भी अन्य तरीके से प्राप्त करने की कोई प्रतिबिंबित क्षमता नहीं है। लेकिन इसे किसी प्रकार के होस्ट दुभाषिया (जैसे ब्राउज़र में) में चलाना है, और इसलिए x में हेरफेर करने के लिए निश्चित रूप से कुछ भयानक तरीका है। एक प्लगइन में एक स्मृति भ्रष्टाचार बग दुर्घटना से ऐसा कर सकता है!

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