2012-02-15 23 views
10

मैंने हाल ही में कुछ मंच पर एक ओओ डिजाइन प्रश्न देखा और आरटीटीआई का उपयोग करने की सोच शुरू कर दी। हालांकि यह खराब डिजाइन होना चाहिए लेकिन मैं एक विकल्प के बारे में सोचने में असमर्थ हूं।ओओ डिजाइन में आरटीटीआई से परहेज

मेरा कुत्ता, बडी नाम है, पिछवाड़े में रहता है -

इस परिदृश्य पर OO अवधारणाओं के उपयोग के लिए एक सी ++ प्रोग्राम बनाएं: यहाँ सरल सवाल है। वह रात में छालता है जब वह एक बिल्ली या गिलहरी देखता है जो यात्रा करने आया है। अगर वह मेंढक देखता है, और वह भूख लगी है, तो वह खाता है। अगर वह एक मेंढक देखता है और वह भूखा नहीं है, तो वह इसके साथ खेलता है। अगर उसने पहले से ही 2 मेंढक खाए हैं, और अभी भी भूखे हैं, तो वह इसे जाने देगा। अगर वह कोयोट देखता है, तो वह मदद के लिए रोता है। कभी-कभी उसका दोस्त स्पॉट बंद हो जाता है, और वे एक-दूसरे का पीछा करते हैं। अगर वह किसी अन्य जानवर को देखता है, तो वह उसे देखता है। मैं उम्मीद करता हूं कि आपके पास पशु वर्ग, और एक बिल्ली, कुत्ता, गिलहरी, कोयोट वर्ग होगा जो पशु वर्ग से विरासत में मिलता है।

मैं कुत्ता वर्ग है जो एक पशु तर्क लेता में एक देखने() विधि होने के बारे में सोच शुरू किया और फिर वस्तु (मेंढक, बिल्ली आदि) के वास्तविक प्रकार की जाँच करता है और आवश्यक कार्रवाई की जाती है - नाटक, पीछा आदि वास्तविक प्रकार के आधार पर। हालांकि इसके लिए आरटीटीआई की आवश्यकता होगी जो खराब डिजाइन होना चाहिए। क्या कोई भी बेहतर डिजाइन सुझा सकता है जो आरटीटीआई से बचने और मेरी सोच में गलती को इंगित करेगा?

+1

मुझे लगता है कि यह प्रश्न प्रोग्रामर.स्टैकएक्सchange.com पर है। –

+1

ए ** बहुत ** महत्वपूर्ण नोट आरटीटीआई है, जैसा कि * कंपाइलर * द्वारा संभाला जाता है, किसी ऑब्जेक्ट को स्वयं पहचानने का एकमात्र तरीका नहीं है। आपके पास 'एनम एनिम टाइप्स' और 'वर्चुअल एनिमल :: गेट टाइप()' विधि, या 'यूयूआईडी अज्ञात :: गेट क्लास()' विधि (एक ला कॉम 'IU अज्ञात :: QueryInterface') या यहां तक ​​कि एक समस्या-विशिष्ट भी हो सकती है 'पशु :: IsScarierThan (पशु * मुझे) '। आरटीटीआई का उपयोग किए बिना रनटाइम प्रकार की जानकारी प्राप्त करने के लिए ऑब्जेक्ट-ओरिएंटेड डिज़ाइन का उपयोग करने के कई तरीके हैं। – ssube

+3

* जो आने के लिए आया है * -> आपका मतलब है कि बिल्ली और गिलहरी * आगंतुक * हैं;)? –

उत्तर

13

आप जिस पर जोर देना चाहते हैं उसके आधार पर "ओओ अवधारणाओं" का उपयोग करके इस समस्या को पूरा करने के लिए हास्यास्पद तरीके से बड़ी संख्या में तरीके हैं।

यहाँ सरल समाधान है कि मैं के साथ आ सकते हैं:

class Animal { 
public: 
    virtual void seenBy(Buddy&) = 0; 
}; 

class Buddy { 
public: 
    void see(Cat&)  { /* ... */ } 
    void see(Squirrel&) { /* ... */ } 
    // ... 
}; 

class Cat : public Animal { 
public: 
    virtual seenBy(Buddy& b) { b.see(*this); } 
}; 

class Squirrel : public Animal { 
public: 
    virtual seenBy(Buddy& b) { b.see(*this); } 
}; 

// classes for Frog, Coyote, Spot... 

आप जानवरों "मानता", अनेक प्रकार के जरूरत है, यह (double dispatch का एक रूप उत्पादन) see के लिए एक आभासी आवरण बनाने के लिए सीधा है:

// On a parent class 
virtual void see(Animal&) = 0; 

// On Buddy 
virtual void see(Animal& a) { a.seenBy(*this); } 

ऊपर Animal वर्ग Buddy के बारे में कुछ पता है कि आवश्यकता है कक्षा।

class Animal { 
public: 
    virtual void visit(Visitor&) = 0; 
}; 

class Cat : public Animal { 
public: 
    virtual void visit(Visitor& v) { v.visit(*this); } 
}; 

class Squirrel : public Animal { 
public: 
    virtual void visit(Visitor& v) { v.visit(*this); } 
}; 

// classes for Frog, Coyote, Spot... 

class Visitor { 
public: 
    virtual void visit(Cat&) = 0; 
    virtual void visit(Squirrel&) = 0; 
    // ... 
}; 

class BuddyVision : public Visitor { 
public: 
    virtual void visit(Cat&)  { /* ... */ } 
    virtual void visit(Squirrel&) { /* ... */ } 
    // ... 
}; 

class Buddy { 
public: 
    void see(Animal& a) { 
     BuddyVision visitor; 
     a.visit(visitor); 
    } 
}; 

दूसरा तंत्र के लिए संभवतः बडी के अलावा अन्य प्रयोजनों के एक जानवर देखने के लिए इस्तेमाल किया जा सकता (: यदि आप अपने तरीकों निष्क्रिय क्रियाओं जा रहा है और Buddy से Animal दसगुणा करना चाहते पसंद नहीं है, तो आप आगंतुक पैटर्न का उपयोग कर सकते हैं वह जानवर बडी देख रहा है)। हालांकि, यह अधिक जटिल है।


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

+0

संकेत: 'BuddyVision()' गैर-कॉन्स्ट संदर्भ के लिए बाध्य नहीं हो सकता है। आपको या तो 'विज़िट' का अधिभार प्रदान करना चाहिए या स्टैक पर नामित तर्क के रूप में इसे तुरंत चालू करना चाहिए (हाँ, यह बेवकूफ है ...)। –

+0

@MatthieuM। फिक्स्ड, धन्यवाद। –

+0

@ जॉन कैल्सबीक: बहुत बहुत धन्यवाद !! – vjain27

3

संकेत: आरटीटीआई के बजाय आभासी कार्यों (लक्षित जानवरों पर) का उपयोग करें।

+0

और वर्चुअल फ़ंक्शन तंत्र RTTI का उपयोग नहीं करता है? ओ.ओ – lapk

+1

असल में आप यह कैसे करेंगे? जानवरों को पता नहीं होना चाहिए कि उन्हें कुत्ते द्वारा देखा जाने पर क्या करना चाहिए? मुझे लगता है कि कुत्ते को जानवर की पहचान करने की आवश्यकता होगी और जो कुछ भी वह चाहता था उसके आधार पर जानवर के रूप में माना जाता था (कोड के संदर्भ में 'स्विच')। मैं वास्तव में इस मामले में आरटीटीआई के साथ जाऊंगा। –

+2

@AzzA nope, यह गतिशील प्रेषण का उपयोग करता है, आरटीटीआई –

6

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

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

इस मामले में, एक इकाई अपनी संपत्तियों के योग के साथ-साथ विभिन्न गुणों के साथ अन्य संस्थाओं का सामना करने के आधार पर व्यवहार से अधिक कुछ नहीं है। इकाई के साथ कुछ राज्य भी हो सकता है। एक विशिष्ट कुत्ता या बिल्ली वर्ग नहीं होगा। बिल्ली की तरह गुणों और व्यवहारों के साथ एक इकाई होगी, और कुत्ते जैसी गुणों और व्यवहार वाले एक इकाई होगी।

+0

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

+0

@ जॉन कॉल्सबेक मैं यह देखने में असफल रहा कि यह किसी भी तरह से "ओओ नहीं" है। यहां तक ​​कि अगर मैं एक संपत्ति-आधारित इकाई परिभाषा प्रणाली को लागू करना चाहता था, तो भी मैं इसे पूरा करने के लिए एक ओओ डिजाइन का उपयोग करता हूं। पृथ्वी पर क्या इस या किसी अन्य मामले में "असली ओओ" का गठन होता है ?? मैंने अपनी डिग्री भी पूरी कर ली है, और मैं यहां कुछ भी नहीं देखता जो ओओपी का उपयोग करके पूरा किया जा सकता है। – TheBuzzSaw

+0

@TheBuzzSaw: जॉन के लिए बात नहीं करना, लेकिन व्यक्तिगत रूप से, मैं "ऑब्जेक्ट ओरिएंटेड" डिज़ाइन पर विचार नहीं करता जब तक कि इसमें विरासत के माध्यम से बहुरूपता शामिल न हो। इसके बिना, यह कुछ भी नहीं है जिसे आप सी –

0

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

other_object->send(IS_SCARRY_OF, this); 

:

क्रमबद्ध की

Id id = object->send(WHO_ARE_YOU); 
switch(id) 
{ 
    case ID_FROG: ...; break; 
    case ID_CAT: ...; break; 
} 

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

+1

यह गैर-कंपाइलर-आधारित आरटीटीआई से अधिक कुछ नहीं है। यह वही अवधारणा है: ऑब्जेक्ट्स में एक पहचानकर्ता होता है जो रनटाइम पर अपना प्रकार निर्धारित करता है। –

+0

@ निकोल बोलास - बिलकुल नहीं, "मैसेजिंग अधिक लचीला है ..." से शुरू होने वाला टेक्स्ट देखें। आरटीटीआई केवल एक "संदेश" का वर्णन करता है - WHO_ARE_YOU प्रति से। –

+1

या आपके पास "is_scarry_of" नामक फ़ंक्शन हो सकता है जो ऑब्जेक्ट लेता है। आप जो कुछ कर रहे हैं वह आभासी प्रेषण और आरटीटीआई की जगह लेने के लिए संदेश भेज रहा है। और इसलिए, दोनों की भाषा सुविधाओं और गारंटी खोना। –

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