2009-10-05 15 views
5

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

उदाहरण के लिए यदि उप-वर्ग डीओएम नोड्स हैं, और यदि एल्गोरिदम एक बच्चे नोड डालना है, तो यह एल्गोरिदम अलग-अलग होता है कि क्या माता-पिता नोड एक डीओएम तत्व (जिसमें बच्चे हो सकते हैं) या डोम टेक्स्ट (जो ' टी): और इतने insertChildren विधि DomNode आधार वर्ग में आभासी (या सार), और DomElement और DomText उपवर्गों में से प्रत्येक में अलग ढंग से लागू किया जा सकता है।

एक और संभावना उदाहरणों को एक आम संपत्ति प्रदान करती है, जिसका मूल्य पढ़ा जा सकता है: उदाहरण के लिए एल्गोरिदम DomNode बेस क्लास की संपत्ति पढ़ सकता है; या किसी अन्य उदाहरण के लिए, आपके पास नेटवर्क पैकेट के विभिन्न प्रकार (उप-वर्ग) हो सकते हैं, जो एक सामान्य पैकेट हेडर साझा करते हैं, और आप यह देखने के लिए पैकेट हेडर पढ़ सकते हैं कि यह किस प्रकार का पैकेट है।

मैं रन-टाइम-प्रकार की जानकारी का उपयोग नहीं किया ज्यादा, सहित:

  • is और as सी #
  • डॉट नेट में
  • Object.GetType विधि downcasting में कीवर्ड
  • typeid ऑपरेटर सी ++

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

मेरा सवाल है, वर्चुअल फ़ंक्शंस के बजाय रन-टाइम-प्रकार की जानकारी का उपयोग करना उचित है?

उत्तर

5

जब कोई अन्य रास्ता नहीं है। वर्चुअल विधियों को हमेशा पसंद किया जाता है लेकिन कभी-कभी उन्हें उपयोग नहीं किया जा सकता है। ऐसा होने के कुछ कारण हैं लेकिन यह आम बात यह है कि आपके पास उन वर्गों का स्रोत कोड नहीं है जिनके साथ आप काम करना चाहते हैं या आप उन्हें बदल नहीं सकते हैं। यह अक्सर होता है जब आप विरासत प्रणाली या बंद स्रोत वाणिज्यिक पुस्तकालय के साथ काम करते हैं।

नेट में यह भी होता है हो सकता है आप प्लग इन की तरह, मक्खी पर नई विधानसभाओं लोड करने के लिए है और आप आम तौर पर कोई आधार वर्ग है, लेकिन बतख टाइपिंग की तरह कुछ का उपयोग करना होगा।

+0

यह कहने का क्या कारण है कि आरटीटीआई को हटा दिया गया है, अंतिम उपाय का एक तरीका? – ChrisW

+2

@ChrisW, यह समझना मुश्किल है और निष्पादित करने में बहुत धीमा है। यह पदावनत नहीं है, यह सिर्फ अन्य तरीके हैं बेहतर :) – vava

+0

वहाँ कोई कारण यह धीमी होने के लिए है: RTTI वर्ग vtable में संग्रहित किया जा सकता है, एक आभासी समारोह सूचक है बस के रूप में। मुझे यकीन नहीं है कि यह समझना मुश्किल क्यों है, या तो, आरटीटीआई की जांच करने के तरीके में अधिक स्थानीय है: उदाहरण के लिए यदि आप देखते हैं कि "अगर (फू फू है)" तो आप जानते हैं कि क्या जा रहा है, बिना परिभाषाओं को देखे और देखे कई subclasses में आभासी कार्यों के। – ChrisW

3

सी ++ में, कुछ अन्य अस्पष्ट मामलों (जो अधिकतर कम डिजाइन विकल्पों से निपटते हैं) के बीच, आरटीटीआई तथाकथित multi methods को लागू करने का एक तरीका है।

+0

यह 'एक' तरीका है, हाँ; http://en.wikipedia.org/wiki/Double_dispatch का उपयोग करने का एक वैकल्पिक तरीका है जो केवल वर्चुअल फ़ंक्शंस का उपयोग करता है: आप पैरामीटर प्रकार के प्रत्येक उप-वर्ग के लिए एक नया वर्चुअल फ़ंक्शन जोड़ना चाहते हैं। – ChrisW

+0

यदि आप मेरे द्वारा पोस्ट किए गए लिंक को देखते हैं, तो आप देखेंगे कि वास्तव में, यह "एकाधिक प्रेषण" की ओर जाता है, जो डबल प्रेषण का सामान्यीकरण है। ':)' – sbi

0

dynamic_cast <>, अगर मैं सही ढंग से याद है, RTTI के आधार पर किया जाता है। कुछ अस्पष्ट बाहरी इंटरफेस आरटीटीआई पर भरोसा कर सकते हैं जब एक ऑब्जेक्ट शून्य सूचक के माध्यम से पारित किया जाता है (किसी भी कारण से हो सकता है)।

कहा जा रहा है, मैं नहीं typeof() जंगली में समर्थक सी ++ रखरखाव के काम के 10 वर्षों में देखा है। (सौभाग्य से।)

+1

टाइपफ को कीवर्ड + कीवर्ड (बहुत उपयोगी, आईएमओ) के रूप में सी ++ 0x के साथ जोड़ा जाएगा।यह रनटाइम प्रकार की जानकारी से संबंधित नहीं है, एक संकलन-समय का निर्माण और सी ++ कंपाइलर की कुछ जानकारी के उत्पादक उपयोग को करने का एक तरीका है, लेकिन वर्तमान में केवल त्रुटि संदेशों में उपयोग करना है। – UncleBens

0

आप किसी मामले के लिए अधिक प्रभावी सी # का संदर्भ ले सकते हैं जहां रन-टाइम प्रकार की जांच ठीक है।

आइटम 3।जेनेरिक एल्गोरिदम का विशेषज्ञ रनटाइम प्रकार का उपयोग

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

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

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

लेकिन आम तौर पर आपको सावधानी से रन-टाइम प्रकार की जांच पर विचार करना चाहिए और यह सुनिश्चित करना चाहिए कि यह लिस्कोव सबस्टिट्यूशन सिद्धांत का उल्लंघन नहीं करता है।

1

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

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

+0

हां, ईवेंट हैंडलर एक अच्छा उदाहरण हैं। अधिक आम तौर पर, जब भी आपका एप्लिकेशन किसी एप्लिकेशन प्रकार पर पॉइंटर स्टोर करना चाहता है, फ्रेमवर्क कोड का उपयोग करके जो आपके एप्लिकेशन प्रकारों को नहीं जानता है; इसमें उदाहरण के लिए डॉट नेट फ्रेमवर्क प्रकारों के 'ऑब्जेक्ट टैग' प्रॉपर्टी' का उपयोग करना शामिल है, और 'शून्य * एलपी पैरामीटर' Win32 'CreateThread' फ़ंक्शन पर पास किया गया है। आप इसे आसानी से पर्याप्त स्टोर कर सकते हैं, लेकिन फिर जब आप इसे वापस प्राप्त करते हैं तो आपको डाउनकास्ट करने की आवश्यकता होती है। – ChrisW

+0

@ChrisW: मुझे नहीं लगता कि आप 'void *' (कम से कम C++ में नहीं) से 'dynamic_cast' कर सकते हैं। संकलक को यह जानने के लिए कैसे पता चलता है कि पते पर पॉलीमोर्फिक प्रकार का एक ऑब्जेक्ट है और इसके आंतरिक डेटा का लेआउट क्या है? – sbi

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