.NET में सभी कक्षाएं विश्व स्तर पर ऑब्जेक्ट क्लास से क्यों विरासत में मिली हैं?


16

मेरे लिए यह बहुत दिलचस्प है कि कौन सा लाभ फ्रेमवर्क के लिए "वैश्विक मूल वर्ग" दृष्टिकोण देता है। सरल शब्दों में, किन कारणों से .NET फ्रेमवर्क को सभी वर्गों के लिए उपयुक्त सामान्य कार्यक्षमता वाले एक रूट ऑब्जेक्ट क्लास के लिए डिज़ाइन किया गया था ।

आजकल हम आंतरिक उपयोग (एसएपी प्लेटफॉर्म के तहत फ्रेमवर्क) के लिए नए ढांचे को डिजाइन कर रहे हैं और हम सभी दो शिविरों में विभाजित हैं - पहला जो सोचता है कि फ्रेमवर्क में वैश्विक जड़ होनी चाहिए, और दूसरा - जो विपरीत सोचता है।

मैं "वैश्विक मूल" शिविर में हूं। और मेरे कारणों से इस तरह के दृष्टिकोण से अच्छे लचीलेपन और विकास लागत में कमी आएगी क्योंकि हम सामान्य कार्यक्षमता को और अधिक विकसित नहीं करेंगे।

इसलिए, मुझे यह जानने में बहुत दिलचस्पी है कि वास्तव में .NET आर्किटेक्ट्स को इस तरह से रूपरेखा तैयार करने के लिए क्या कारण हैं।


6
याद रखें कि .NET फ्रेमवर्क एक सामान्यीकृत सॉफ़्टवेयर डेवलपमेंट वातावरण का हिस्सा है। फ्रेमवर्क जो आपके जैसे अधिक विशिष्ट हैं, उन्हें "मूल" ऑब्जेक्ट की आवश्यकता नहीं हो सकती है। objectभाग में .NET फ्रेमवर्क में एक जड़ है क्योंकि यह सभी वस्तुओं में कुछ बुनियादी क्षमताओं को प्रदान करता है, जैसे कि ToString()औरGetHashCode()
रॉबर्ट हार्वे

10
"मैं यह जानना बहुत दिलचस्प हूं कि वास्तव में .NET आर्किटेक्ट्स को इस तरह से रूपरेखा तैयार करने के लिए क्या कारण हैं।" इसके तीन बहुत अच्छे कारण हैं: 1. जावा ने इसे इस तरह से किया, 2. जावा ने इसे इस तरह से किया, और 3. जावा ने इसे इस तरह से किया।
dasblinkenlight

2
@vcsjones: और उदाहरण के लिए जावा पहले से wait()/ notify()/ notifyAll()और के साथ प्रदूषित है clone()
जोकिम सॉयर

3
@daskblinkenlight Thats पू। जावा ने ऐसा नहीं किया।
दांते

2
@dasblinkenlight: FYI करें, जावा वर्तमान में C # की प्रतिलिपि बना रहा है, जिसमें लैम्ब्डा, LINQ फ़ंक्शंस, आदि ...
user541686

जवाबों:


18

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


6
यह सही जवाब है। सामान्य समर्थन का अभाव ही एकमात्र कारण था। अन्य "सामान्य-विधियाँ" तर्क वास्तविक तर्क नहीं हैं क्योंकि सामान्य विधियों को सामान्य होने की आवश्यकता नहीं है - उदाहरण: 1) ToString: अधिकांश मामलों में दुर्व्यवहार किया जाता है; 2) GetHashCode: प्रोग्राम क्या करता है, इसके आधार पर, अधिकांश वर्गों को इस पद्धति की आवश्यकता नहीं है; 3)
गेट टाइप:

2
किस तरह से .NET "पूरी तरह से हर प्रकार की सुरक्षा को खो देता है" इस विचार को "दुरुपयोग" करके कि सब कुछ एक विशिष्ट वर्ग से प्राप्त होना चाहिए? क्या कोई शिटकोड है जिसे C ++ में Objectचारों ओर नहीं लिखा जा सकता है void *
कार्सन 63000

3
किसने कहा कि मुझे लगा void*कि कोई बेहतर है? यह नहीं है। अगर कुछ भी। यह और भी बुरा है
डेडएमजी जूल

void*सभी अंतर्निहित सूचक जातियों के साथ C में बदतर है, लेकिन C ++ इस संबंध में अधिक सख्त है। कम से कम आपको स्पष्ट रूप से डालना होगा।
तमसे सजेलेई

2
@ फिश: एक शब्दावली वक्रोक्ति: सी में, "निहित कलाकार" जैसी कोई चीज नहीं है। एक कास्ट एक स्पष्ट ऑपरेटर है जो रूपांतरण निर्दिष्ट करता है। आपका मतलब है "निहित सूचक रूपांतरण "।
कीथ थॉम्पसन

11

मुझे एक बार एरिक लिपर्ट याद आया कि System.Objectकक्षा से विरासत में 'ग्राहक के लिए सर्वोत्तम मूल्य' प्रदान किया गया। [संपादित करें: हां, उन्होंने यहां कहा ]:

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

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

यह एक बहुत अस्पष्ट जवाब है। यदि आप अधिक विशिष्ट उत्तर चाहते हैं, तो अधिक विशिष्ट प्रश्न पूछने का प्रयास करें।

System.Objectकक्षा से प्राप्त होने वाली हर चीज एक विश्वसनीयता और उपयोगिता प्रदान करती है जो कि मुझे बहुत सम्मान देने के लिए आई है। मुझे पता है कि सभी वस्तुओं का एक प्रकार ( GetType) होगा, कि वे सीएलआर के अंतिम तरीकों ( Finalize) के अनुरूप होंगे , और यह कि मैं GetHashCodeसंग्रह के साथ काम करते समय उन पर उपयोग कर सकता हूं ।


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

5
नहीं, यह त्रुटिपूर्ण नहीं कर रहा है - मैं दावा किया कभी नहीं है कि आप का प्रयोग करेंगे GetType, Finalizeया, GetHashCodeहर के लिए System.Object। मैंने केवल इतना कहा कि यदि आप उन्हें चाहते थे तो वे वहां थे। "उनके इंटरफेस को अनावश्यक रूप से प्रदूषित करने के लिए" के रूप में, मैं एलिपर्ट के अपने मूल उद्धरण का उल्लेख करूंगा: "ग्राहक के लिए सर्वोत्तम मूल्य"। जाहिर है कि .NET टीम ट्रेडऑफ से निपटने के लिए तैयार थी।
gws2

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

मैं आपकी बात पर बहस करने की कोशिश नहीं कर रहा हूं @DeadMG - सवाल यह था कि "विशेष रूप से .NET में सभी कक्षाएं विश्व स्तर पर ऑब्जेक्ट क्लास से क्यों विरासत में मिली हैं" और इस प्रकार मैं किसी पिछले पोस्ट से जुड़ा हुआ हूं। जो कि .NET टीम के बहुत करीब है। Microsoft जो एक वैध - यद्यपि अस्पष्ट - उत्तर दिया था क्यों .NET विकास टीम ने इस दृष्टिकोण को चुना।
gw2 2

इस सवाल का जवाब देने के लिए बहुत अस्पष्ट।
डेडएमजी

4

मुझे लगता है कि जावा और सी # डिजाइनरों ने एक रूट ऑब्जेक्ट जोड़ा क्योंकि यह अनिवार्य रूप से उनके लिए मुफ्त था, जैसा कि मुफ्त दोपहर के भोजन में

किसी रूट ऑब्जेक्ट को जोड़ने की लागत आपके पहले वर्चुअल फ़ंक्शन को जोड़ने की लागत के बराबर होती है। चूंकि सीएलआर और जेवीएम दोनों ऑब्जेक्ट फाइनलर्स के साथ कचरा एकत्र किए गए वातावरण हैं, इसलिए आपको अपने java.lang.Object.finalizeया अपने System.Object.Finalizeतरीके के लिए कम से कम एक आभासी होना चाहिए । इसलिए, अपनी मूल वस्तु को जोड़ने की लागत पहले से ही प्रीपेड है, आप इसके लिए भुगतान किए बिना सभी लाभ प्राप्त कर सकते हैं। यह दोनों दुनिया के लिए सबसे अच्छा है: जिन उपयोगकर्ताओं को एक सामान्य रूट वर्ग की आवश्यकता होती है उन्हें वही मिलेगा जो वे चाहते हैं, और जो उपयोगकर्ता कम देखभाल नहीं कर सकते हैं वे प्रोग्राम करने में सक्षम होंगे जैसे कि यह वहां नहीं है।


4

मुझे लगता है कि आपके पास यहां तीन प्रश्न हैं: एक यह है कि एक सामान्य रूट को .NET में क्यों पेश किया गया था, दूसरा वह है जो उस के फायदे और नुकसान हैं, और तीसरा यह है कि क्या एक फ्रेमवर्क तत्व के लिए एक वैश्विक विचार है जड़।

.NET के पास एक सामान्य जड़ क्यों है?

सबसे तकनीकी अर्थ में, एक सामान्य जड़ प्रतिबिंब के लिए और पूर्व-जेनेरिक कंटेनरों के लिए आवश्यक है

मेरे ज्ञान के अतिरिक्त, आधार विधियों के साथ एक सामान्य जड़ होने equals()और hashCode()जावा में बहुत सकारात्मक रूप से प्राप्त किया गया था, और C # जावा (दूसरों के बीच) से प्रभावित था, इसलिए वे उस सुविधा को भी चाहते थे।

किसी भाषा में एक सामान्य जड़ होने के क्या फायदे और नुकसान हैं?

एक आम जड़ होने का लाभ:

  • आप सभी वस्तुओं को एक निश्चित कार्यक्षमता रखने की अनुमति दे सकते हैं , जिसे आप महत्वपूर्ण मानते हैं, जैसे equals()और hashCode()। उदाहरण के लिए, उदाहरण के लिए, कि जावा या C # में प्रत्येक ऑब्जेक्ट का उपयोग हैश मैप में किया जा सकता है - उस स्थिति की C ++ से तुलना करें।
  • आप अज्ञात प्रकार की वस्तुओं का उल्लेख कर सकते हैं - उदाहरण के लिए, यदि आप सिर्फ सूचनाओं को स्थानांतरित करते हैं, जैसा कि पूर्व-जेनेरिक कंटेनरों ने किया था।
  • आप अनजाने प्रकार की वस्तुओं का उल्लेख कर सकते हैं - जैसे प्रतिबिंब का उपयोग करते समय।
  • इसका उपयोग दुर्लभ मामलों में किया जा सकता है जब आप एक ऐसी वस्तु को स्वीकार करने में सक्षम होना चाहते हैं जो भिन्न और अन्यथा असंबंधित प्रकार की हो सकती है - जैसे कि एक printf-जैसे विधि के एक पैरामीटर के रूप में ।
  • यह आपको सिर्फ एक वर्ग को बदलकर सभी वस्तुओं के व्यवहार को बदलने की सुविधा देता है। उदाहरण के लिए, यदि आप अपने C # प्रोग्राम में सभी ऑब्जेक्ट्स के लिए एक विधि जोड़ना चाहते हैं, तो आप एक एक्सटेंशन विधि जोड़ सकते हैं object। बहुत आम नहीं, शायद, लेकिन एक आम जड़ के बिना यह संभव नहीं होगा।

आम जड़ होने का नुकसान:

  • कुछ मूल्य की एक वस्तु को संदर्भित करने के लिए इसका दुरुपयोग किया जा सकता है, भले ही आप इसके लिए अधिक सटीक प्रकार का उपयोग कर सकते थे।

क्या आपको अपनी रूपरेखा परियोजना में एक सामान्य जड़ के साथ जाना चाहिए?

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

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

बेशक, उस प्रकार के लिए कम से कम थोड़ा सा संबंधित होना चाहिए , और विशेष रूप से, मैं कभी भी एक सामान्य रूट के लिए "is-a" नियम का त्याग नहीं करूंगा।


मुझे लगता है कि c # केवल जावा से प्रभावित नहीं था, यह कुछ बिंदुओं पर है- जावा। Microsoft अब जावा का उपयोग नहीं कर सकता है ताकि निवेश में अरबों की कमी हो। उन्होंने भाषा देने के साथ शुरू किया कि उनके पास पहले से ही एक नया नाम था।
माइक ब्रॉन

3

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

यदि आप एक रूपरेखा बना रहे हैं, तो जरूरी चीजें मौजूदा कोडबेस द्वारा खपत की जाएंगी। आपके पास एक सार्वभौमिक सुपरटेप नहीं हो सकता है क्योंकि सभी प्रकार के सभी में जो भी ढांचा मौजूद है उसका उपभोग करता है।

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

लेकिन ऐसा होता है। यदि ऐसा होता है, तो उस सामान्य व्यवहार को अमूर्त करने में आगे बढ़ें।


2

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

ध्यान रखें कि वे किसी भी OOP सिद्धांतों या किसी भी चीज़ का उल्लंघन नहीं कर रहे हैं। ऑब्जेक्ट क्लास में कुछ भी सिस्टम में किसी भी उपवर्ग (पढ़ें: किसी भी वर्ग) में समझ में आता है। यदि आप इस डिज़ाइन को अपनाना चाहते हैं, तो सुनिश्चित करें कि आप इस पैटर्न का पालन करते हैं। यही है, रूट में ऐसी चीजें शामिल न करें जो आपके सिस्टम में हर, सिंगल क्लास में न हों। यदि आप इस नियम का ध्यानपूर्वक पालन करते हैं, तो मुझे कोई कारण नहीं दिखाई देता है कि आपके पास रूट सिस्टम नहीं होना चाहिए जिसमें पूरे सिस्टम के लिए उपयोगी, समान कोड हो।


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

2

कारणों की एक जोड़ी, सामान्य कार्यक्षमता सभी बच्चे वर्ग साझा कर सकते हैं। और इसने फ्रेमवर्क लेखकों को बहुत सारी अन्य कार्यक्षमता को लिखने की क्षमता प्रदान की, जो सब कुछ उपयोग कर सकते हैं। एक उदाहरण ASP.NET कैशिंग और सत्र होगा। उनमें लगभग कुछ भी संग्रहीत किया जा सकता है, क्योंकि उन्होंने वस्तुओं को स्वीकार करने के लिए तरीके जोड़े।

एक जड़ वर्ग बहुत आकर्षक हो सकता है, लेकिन यह बहुत, दुरुपयोग करने के लिए बहुत आसान है। क्या इसकी बजाय रूट इंटरफ़ेस करना संभव होगा? और सिर्फ एक या दो छोटे तरीके हैं? या कि आपके ढांचे के लिए आवश्यकता से अधिक कोड जोड़ देगा?

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

कई साल पहले एक बहुत बड़ा अनुप्रयोग था जहाँ मैंने एक रूट क्लास बनाया। विकास के कुछ महीनों के बाद इसे कोड द्वारा आबाद किया गया था जिसमें कोई व्यवसाय नहीं था। हम एक पुराने एएसपी एप्लिकेशन को परिवर्तित कर रहे थे और रूट क्लास पुराने Global.inc फाइल का प्रतिस्थापन था जिसे हमने अतीत में उपयोग किया था। उस पाठ को कठिन तरीके से सीखना था।


2

सभी स्टैंडअलोन हीप ऑब्जेक्ट्स से विरासत में मिलते हैं Object; यह समझ में आता है क्योंकि सभी स्टैंडअलोन हीप ऑब्जेक्ट्स में कुछ सामान्य पहलू होने चाहिए, जैसे कि उनके प्रकार की पहचान करने का एक साधन। अन्यथा, यदि कचरा-कलेक्टर के पास अज्ञात प्रकार के ढेर ऑब्जेक्ट का संदर्भ था, तो यह जानने का कोई तरीका नहीं होगा कि उस ऑब्जेक्ट से जुड़ी स्मृति की बूँद के भीतर किन बिट्स को अन्य हीप वस्तुओं के संदर्भ के रूप में माना जाना चाहिए।

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

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

यह सब महत्वपूर्ण है क्योंकि मूल्य-प्रकार के ढेर वस्तुओं के संदर्भ वर्ग के संदर्भों की तरह व्यवहार करते हैं और मूल्य प्रकारों की तरह नहीं। उदाहरण के लिए, निम्नलिखित कोड पर विचार करें:

string testEnumerator <T> (T it) जहां T: IEnumerator <string>
{
  var it2 = it;
  it.MoveNext ();
  it2.MoveNext ();
  इसे वापस करो।
}
सार्वजनिक शून्य परीक्षण ()
{
  var theList = नई सूची <string> ();
  theList.Add ( "फ्रेड");
  theList.Add ( "जॉर्ज");
  theList.Add ( "पर्सी");
  theList.Add ( "मौली");
  theList.Add ( "रॉन");

  var enum1 = theList.GetEnumerator ();
  IEnumerator <string> enum2 = enum1;

  Debug.Print (testEnumerator (enum1));
  Debug.Print (testEnumerator (enum1));
  Debug.Print (testEnumerator (enum2));
  Debug.Print (testEnumerator (enum2));
}

यदि testEnumerator()विधि को मान प्रकार का संग्रहण स्थान दिया जाता है, itतो एक उदाहरण प्राप्त होगा जिसके सार्वजनिक और निजी क्षेत्रों को पारित मूल्य से कॉपी किया जाता है। स्थानीय वैरिएबल it2एक और उदाहरण देगा जिसके क्षेत्र सभी से कॉपी किए गए हैं it। कॉल करने MoveNextपर it2असर नहीं पड़ेगा it

यदि उपरोक्त कोड को क्लास के प्रकार का भंडारण स्थान दिया गया है, तो पारित मूल्य, itऔर it2, सभी एक ही ऑब्जेक्ट को संदर्भित करेंगे, और इस प्रकार MoveNext()उनमें से किसी पर कॉल करना प्रभावी रूप से उन सभी पर कॉल करेगा।

ध्यान दें कि कास्टिंग List<String>.Enumeratorके लिए IEnumerator<String>प्रभावी रूप से एक वर्ग प्रकार के एक मान प्रकार से यह बदल जाता है। हीप ऑब्जेक्ट का प्रकार है, List<String>.Enumeratorलेकिन इसका व्यवहार एक ही नाम के मूल्य प्रकार से बहुत अलग होगा।


+1 ToString () का उल्लेख नहीं करने के लिए
जेफो

1
यह सभी कार्यान्वयन विवरण के बारे में है। उपयोगकर्ता को इन्हें उजागर करने की कोई आवश्यकता नहीं है।
डेडएमजी जूल

@DeadMG: आपका क्या मतलब है? एक के List<T>.Enumeratorरूप में संग्रहित किया List<T>.Enumeratorजाने वाला व्यवहार एक के व्यवहार से काफी अलग होता है जो एक में संग्रहीत होता है IEnumerator<T>, जिसमें पूर्व प्रकार के मूल्य को किसी भी प्रकार के भंडारण स्थान पर संग्रहीत करना एन्यूमरेटर की स्थिति की प्रतिलिपि बना देगा, भंडारण प्रकार के लिए बाद के प्रकार का मान संग्रहीत करते समय, जो बाद के प्रकार का भी है, प्रतिलिपि नहीं बनाएगा।
सुपरकैट

हाँ, पर Objectहै कुछ भी नहीं है कि इस तथ्य से कोई लेना देना।
डेडएमजी जूल

@DeadMG: मेरा कहना है कि एक प्रकार System.Int32का ढेर उदाहरण भी एक उदाहरण है System.Object, लेकिन प्रकार System.Int32का भंडारण स्थान न तो System.Objectउदाहरण है और न ही किसी का संदर्भ है।
सुपरकैट

2

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

Objectरूट पर एक एकल पदानुक्रम (या कुछ समान) होने से आपके संग्रह वर्गों के संग्रह के रूप में बनाने के लिए (एक उदाहरण के लिए) काफी आसान हो जाता है Object, इसलिए किसी भी प्रकार की वस्तु को संग्रह करने के लिए यह तुच्छ है।

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

70 के दशक में जब स्मॉलटाक को डिजाइन किया जा रहा था, इस तरह की बकवास को स्वीकार किया गया था, मुख्यतः क्योंकि किसी ने भी एक उचित विकल्प नहीं बनाया था। स्मॉलटाक को 1980 में अंतिम रूप दिया गया था, और 1983 तक Ada (जिसमें जेनरिक भी शामिल है) डिजाइन किया गया था। यद्यपि अडा ने कभी भी उस तरह की लोकप्रियता हासिल नहीं की, जिसकी भविष्यवाणी की गई थी, इसके जेनेरिक, मनमाने ढंग से पदानुक्रमों में निहित पागलपन के बिना - मनमाने प्रकार की वस्तुओं के संग्रह का समर्थन करने के लिए पर्याप्त थे ।

जब जावा (और कुछ हद तक, .NET) डिजाइन किए गए थे, तो अखंड वर्ग पदानुक्रम शायद "सुरक्षित" विकल्प के रूप में देखा गया था - समस्याओं के साथ, लेकिन ज्यादातर ज्ञात समस्याएं। जेनेरिक प्रोग्रामिंग, इसके विपरीत, लगभग हर कोई (तब भी) महसूस किया गया था कि कम से कम सैद्धांतिक रूप से समस्या के लिए बहुत बेहतर दृष्टिकोण था, लेकिन एक यह कि कई व्यावसायिक रूप से उन्मुख डेवलपर्स को बल्कि खराब खोज और / या जोखिम भरा माना जाता था (यानी, वाणिज्यिक दुनिया में) , एडा को काफी हद तक एक विफलता के रूप में खारिज कर दिया गया था)।

मुझे स्पष्ट होने दो हालांकि: अखंड पदानुक्रम एक गलती थी। उस गलती के कारणों को कम से कम समझा जा सकता था, लेकिन यह वैसे भी एक गलती थी। यह एक बुरा डिज़ाइन है, और इसकी डिज़ाइन समस्याओं का उपयोग करते हुए लगभग सभी कोड व्याप्त हैं।

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


यह बताया गया है कि .NET को शिप करने से पहले टेम्प्लेट भयानक और उपयोगी होने के लिए जाना जाता था।
डेडएमजी

वाणिज्यिक दुनिया में, Ada एक विफलता थी, इसकी क्रियाशीलता के कारण ऐसा नहीं था , लेकिन ऑपरेटिंग सिस्टम सेवाओं के लिए मानकीकृत इंटरफेस की कमी के कारण। फ़ाइल सिस्टम, ग्राफिक्स, नेटवर्क, आदि के लिए कोई मानक एपीआई ने 'होस्टेड' अनुप्रयोगों के एडा विकास को बहुत महंगा बना दिया।
केविन क्लाइन

@kevincline: मुझे शायद यह कहना चाहिए था कि थोड़ा-सा प्रभाव - बाजार में अपनी विफलता के कारण एक पूरे के रूप में एडीए को खारिज कर दिया गया था। एडीए का उपयोग करने से इनकार करना (आईएमओ) काफी उचित था - लेकिन इससे बहुत कम (सबसे अच्छा) सीखने से इनकार करना।
जेरी कॉफिन

@ जेरी: मुझे लगता है कि सी ++ टेम्पलेट्स ने एडीए जेनरिक के विचारों को अपनाया, फिर निहित तात्कालिकता के साथ उन्हें बहुत सुधार दिया।
केविन क्लाइन

1

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

यहां कुछ बातें सोचने वाली हैं:

  • आप कभी भी जानबूझकर इस शीर्ष-स्तरीय ऑब्जेक्ट को अधिक विशिष्ट ऑब्जेक्ट पर कैसे पास करेंगे?
  • आपकी हर एक कक्षा को किस कोड में रखने का इरादा है?

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

व्यक्तिगत अनुभव से भी:

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

मेरे द्वारा निपटाए गए पुस्तकालय का उपयोग करना सबसे कठिन था।


0

क्योंकि यह OOP का तरीका है। एक प्रकार (ऑब्जेक्ट) होना महत्वपूर्ण है जो किसी भी चीज़ को संदर्भित कर सकता है। प्रकार वस्तु का एक तर्क कुछ भी स्वीकार कर सकता है। वहाँ भी विरासत है, आप सुनिश्चित कर सकते हैं कि ToString (), GetHashCode () आदि कुछ भी और सब कुछ पर उपलब्ध हैं।

यहां तक ​​कि ओरेकल ने इस तरह के आधार प्रकार के महत्व को महसूस किया है और 2017 के पास जावा में आदिमता को दूर करने की योजना बना रहा है


6
यह न तो ओओपी का तरीका है और न ही महत्वपूर्ण है। आप "यह अच्छा है" के अलावा कोई वास्तविक तर्क नहीं देते हैं।
डेडएमजी

1
@DeadMG आप पहले वाक्य के पिछले तर्कों को पढ़ सकते हैं। इस प्रकार प्रोग्रामर ऑब्जेक्ट्स और प्राइमेटिव्स के लिए एक ही उद्देश्य कोड के कई वेरिएंट लिखने के लिए मजबूर करने के लिए प्राइमरिटिज़ ऑब्जेक्ट्स की तुलना में अलग व्यवहार करता है।
दांते

2
@DeadMG अच्छी तरह से उन्होंने कहा कि इसका मतलब है कि आप मान सकते हैं ToString()और GetType()हर वस्तु पर होगा। यह संभवतः इंगित करने योग्य है कि आप objectकिसी भी .NET ऑब्जेक्ट को स्टोर करने के लिए एक प्रकार का चर का उपयोग कर सकते हैं ।
जॉनएल

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

आपके पास केवल स्तरों पर एक ऑब्जेक्ट होना चाहिए जिसमें विशिष्ट कोड होते हैं, आपके पास कभी भी ऐसा नहीं होना चाहिए कि आप अपने ग्राफ को एक साथ जोड़ सकें। "ऑब्जेक्ट" वास्तव में कुछ महत्वपूर्ण तरीकों को लागू करता है और ऑब्जेक्ट को टूलिंग में पास करने के तरीके के रूप में कार्य करता है जहां प्रकार अभी तक नहीं बनाया गया है।
बिल के
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.