एक पदानुक्रम को मजबूर किए बिना मैं एक दूसरे के साथ बातचीत और संवाद करने वाली वस्तुएं कैसे हो सकती हैं?


9

मुझे उम्मीद है कि ये रैलिंग मेरे सवाल को स्पष्ट कर देंगी - अगर वे अभ्यस्त हैं तो मैं पूरी तरह से समझ पाऊंगा, इसलिए मुझे बताएं कि क्या यह मामला है, और मैं खुद को स्पष्ट करने की कोशिश करूंगा।

बॉक्सपोंग से मिलो , एक बहुत ही सरल गेम जिसे मैंने ऑब्जेक्ट-ओरिएंटेड गेम डेवलपमेंट से परिचित कराया। गेंद को नियंत्रित करने और पीली चीजों को इकट्ठा करने के लिए बॉक्स को खींचें।
बॉक्सपॉन्ग बनाने से मुझे अन्य बातों के अलावा, एक मौलिक प्रश्न: मुझे एक-दूसरे से "संबंधित" होने के बिना एक दूसरे के साथ बातचीत करने वाली वस्तुएं कैसे मिल सकती हैं? दूसरे शब्दों में, क्या वस्तुओं के लिए एक तरीका है पदानुक्रमित नहीं, बल्कि सह-अस्तित्ववादी? (मैं नीचे और विस्तार में जाऊंगा।)

मुझे लगता है कि सह-अस्तित्व वाली वस्तुओं की समस्या एक आम बात है, इसलिए मुझे उम्मीद है कि इसे हल करने के लिए एक स्थापित तरीका है। मैं स्क्वायर व्हील को सुदृढ़ नहीं करना चाहता, इसलिए मुझे लगता है कि मैं जिस आदर्श उत्तर की तलाश कर रहा हूं वह है "यहां एक डिज़ाइन पैटर्न है जो आमतौर पर आपकी तरह की समस्या को हल करने के लिए उपयोग किया जाता है।"

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

एक दूसरे के बीच जानकारी पास करने के लिए आवश्यक वस्तुओं का मुद्दा भी है। मेरे पास एसएनईएस के लिए कोड लिखने का काफी अनुभव है, जहां आपको हर समय व्यावहारिक रूप से पूरी रैम तक पहुंच है। कहते हैं कि आप सुपर मारियो वर्ल्ड के लिए एक कस्टम दुश्मन बना रहे हैं , और आप चाहते हैं कि यह मारियो के सभी सिक्कों को हटा दे, फिर $ 0DBF को संबोधित करने के लिए शून्य को स्टोर करें, कोई बात नहीं। यह कहते हुए कोई सीमा नहीं है कि दुश्मन खिलाड़ी की स्थिति तक नहीं पहुंच सकते। मुझे लगता है कि मैं इस स्वतंत्रता से खराब हो गया हूं, क्योंकि सी ++ और जैसे मैं अक्सर खुद को आश्चर्यचकित करता हूं कि कुछ अन्य वस्तुओं (या यहां तक ​​कि वैश्विक) के लिए सुलभ मूल्य कैसे बनाया जाए।
BoxPong के उदाहरण का उपयोग करते हुए, क्या होगा अगर मैं स्क्रीन के किनारों से गेंद को उछाल देना चाहता था? widthऔर वर्ग के heightगुण हैं Game,ballउन तक पहुँचने के लिए। मैं इस प्रकार के मूल्यों को (या तो निर्माणकर्ताओं या उन विधियों के माध्यम से पारित कर सकता हूँ जहाँ वे आवश्यक हैं), लेकिन यह मेरे लिए बुरे अभ्यास को चिल्लाता है।

मुझे लगता है कि मेरी मुख्य समस्या यह है कि मुझे एक दूसरे को जानने के लिए वस्तुओं की आवश्यकता है, लेकिन एकमात्र तरीका जो मैं कर सकता हूं वह है सख्त पदानुक्रम, जो बदसूरत और अव्यवहारिक है।

मैंने C ++ पर "फ्रेंड क्लासेस" के बारे में सुना है और पता है कि वे कैसे काम करते हैं, लेकिन अगर वे एंड-ऑल सॉल्यूशन हैं, तो मैं कैसे आऊं, friendहर एक C ++ प्रोजेक्ट पर सभी कीवर्ड डाले नहीं गए , और कैसे आए अवधारणा हर OOP भाषा में मौजूद नहीं है? (वही फंक्शन पॉइंटर्स के लिए जाता है, जो मैंने हाल ही में सीखा है।)

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


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

कक्षाओं को एक दूसरे के ज्ञान के बिना एक दूसरे के साथ सहयोग करने की अनुमति देने की समस्या को मध्यस्थ डिजाइन पैटर्न द्वारा हल किया जाता है। क्या आपने इसे देखा है?
फुहारमेनटर

जवाबों:


13

सामान्य तौर पर, यह बहुत बुरी तरह से बदल जाता है अगर एक ही स्तर की वस्तुओं को एक-दूसरे के बारे में पता हो। एक बार वस्तुओं को एक दूसरे के बारे में पता होने के बाद वे बंधे होते हैं, या एक दूसरे के साथ जुड़ जाते हैं । यह उन्हें बदलने के लिए कठिन, परीक्षण करने के लिए कठिन, बनाए रखने के लिए कठिन बनाता है।

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

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


2

BoxPong के उदाहरण का उपयोग करते हुए, क्या होगा यदि मैं स्क्रीन के किनारों से गेंद को उछाल देना चाहता था? चौड़ाई और ऊंचाई खेल वर्ग के गुण हैं, और मुझे उन तक पहुंचने के लिए गेंद की आवश्यकता होगी।

नहीं!

मुझे लगता है कि आपके पास जो मुख्य मुद्दा है, क्या आप "ऑब्जेक्ट ओरिएंटेड प्रोग्रामिंग" को थोड़ा बहुत शाब्दिक रूप से ले रहे हैं। ओओपी में, एक वस्तु एक "चीज़" का प्रतिनिधित्व नहीं करती है, लेकिन एक "विचार" का अर्थ है कि एक "बॉल", "गेम", "भौतिकी", "मैथ", "दिनांक", आदि सभी वैध वस्तुएं हैं। वस्तुओं के लिए किसी भी चीज़ के बारे में "पता" करने की भी आवश्यकता नहीं है। उदाहरण के लिए, Date.Now().getTommorrow()कंप्यूटर से पूछेंगे कि आज का दिन क्या है, कल की तारीख का पता लगाने के लिए आर्कन डेट नियम लागू करें और कॉल करने वाले को वापस कर दें। Dateवस्तु पता नहीं के बारे में कुछ और, यह केवल अनुरोध जानकारी के रूप में सिस्टम से जरूरत की जरूरत है। इसके अलावा, Math.SquareRoot(number)वर्गमूल की गणना करने के तरीके के तर्क के अलावा कुछ भी जानने की जरूरत नहीं है।

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

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

और अपने मारियो उदाहरण में, क्या आप एक चुनौती कमरे में जहां एक दुश्मन को छू Marios सिक्के नाली नहीं करता है में हैं, लेकिन सिर्फ उसे उस कमरे से बाहर निकालता है? यह मारियो के विचार अंतरिक्ष या दुश्मन कि मारियो जब एक दुश्मन को छू सिक्के खो चाहिए बाहर है (वास्तव में, यदि मारियो एक अकाटता स्टार है, वह दुश्मन के बजाय मारता है)। तो जो कुछ भी वस्तु (डोमेन / विचार) है कि क्या होता है जब मारियो छू लेती है एक दुश्मन केवल एक ही है कि जरूरतों के बारे में या तो पता करने के लिए है के लिए जिम्मेदार है, और जो यह उनमें से या तो करने के लिए (हद तक करना चाहिए कि वस्तु बाहरी प्रेरित परिवर्तन की अनुमति देता है कि )।

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

सीखना कैसे, स्पष्ट पृथक, अच्छी तरह से परिभाषित, और आसान करने के लिए उपयोग ब्लॉक में आपके डोमेन विचारों को परिभाषित करने के लिए कितनी अच्छी तरह आप OOP का उपयोग कर सकते में सबसे बड़ा कारक हो जाएगा।


1

मिलिए BoxPong, एक बहुत ही सरल खेल मैं वस्तु उन्मुख खेल विकास के साथ परिचित हो बनाया है।

एक बुनियादी सवाल BoxPong मदद की मुझे तैयार, अन्य बातों के अलावा बनाना: कैसे मैं वस्तुओं हो सकता है "संबंधित" करने के लिए एक दूसरे के बिना दूसरे के साथ सहभागिता?

मैं SNES, जहां व्यावहारिक रूप से पूरे रैम के लिए उपयोग हर समय के लिए अनुभव लेखन कोड की काफ़ी है। आप सुपर मारियो विश्व के लिए एक कस्टम दुश्मन बना रहे हैं का कहना है कि, और आप इसे मारियो के सिक्कों की सभी निकालना चाहते हैं, तो बस का पता $ 0DBF, कोई समस्या नहीं करने के लिए शून्य की दुकान।

आप ऑब्जेक्ट ओरिएंटेड प्रोग्रामिंग की बात को अनदेखा होना दिखाई देते हैं।

ऑब्जेक्ट ओरिएंटेड प्रोग्रामिंग आपके आर्किटेक्चर में कुछ प्रमुख निर्भरता को चुनकर निर्भरता को प्रबंधित करने के बारे में है ताकि आप कठोरता, नाजुकता और गैर-पुन: प्रयोज्य को रोक सकें।

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

ऑब्जेक्ट ओरिएंटेड कोड आपके कोड को अमूर्त बनाने पर निर्भर करता है और विवरण पर नहीं। इसलिए इसके बजाय

class Mario
{
    public:
        int coins;
}

आप लिखेंगे

class Mario
{
    public:
        void LoseCoins();

    private:
        int coins;
}

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

इसलिए, जब आप पूछें

मेरे पास ऐसी वस्तुएं कैसे हो सकती हैं जो एक-दूसरे के साथ "दूसरे" के बिना एक दूसरे के साथ बातचीत करती हैं?

तुम सच पूछ रहे हो:

मेरे पास ऐसा कोड कैसे हो सकता है जो बिना किसी सार के सीधे एक दूसरे पर निर्भर हो?

जो ऑब्जेक्ट ओरिएंटेड प्रोग्रामिंग नहीं है।

मेरा सुझाव है कि आप यहां सब कुछ पढ़ना शुरू करें: http://objectmentor.com/omSolutions/oops_what.html और फिर रॉबर्ट मार्टिन द्वारा सब कुछ के लिए यूट्यूब खोजें और यह सब देखें।

मेरे उत्तर उससे निकलते हैं, और कुछ सीधे उससे उद्धृत किए जाते हैं।


उत्तर के लिए धन्यवाद (और आप जिस पेज से जुड़े हैं; दिलचस्प लग रहा है)। मैं वास्तव में अमूर्तता और पुन: प्रयोज्य के बारे में जानता हूं, लेकिन मुझे लगता है कि मैंने अपने उत्तर में बहुत अच्छी तरह से नहीं डाला। हालाँकि, आपके द्वारा दिए गए उदाहरण कोड से मैं अपनी बात को बेहतर ढंग से समझा सकता हूँ! आप मूल रूप से कह रहे हैं कि दुश्मन वस्तु को ऐसा नहीं करना चाहिए mario.coins = 0;, लेकिन mario.loseCoins();, जो ठीक है और सच है - लेकिन मेरी बात यह है कि दुश्मन को marioकिसी भी तरह से वस्तु तक पहुंच कैसे हो सकती है? marioएक सदस्य परिवर्तनशील enemyहोना मुझे सही नहीं लगता।
vvye

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

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

@Tezra लेकिन फिर, ये उच्च क्रम की वस्तुएं पुन: प्रयोज्य नहीं हैं? ऐसा लगता है कि ये ऑब्जेक्ट कार्य के रूप में कार्य करते हैं, वे केवल उस प्रक्रिया का अस्तित्व रखते हैं जो वे प्रदर्शित करते हैं।
स्टीव चामिलार्ड

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

0

आप मध्यस्थ पैटर्न लागू करके ढीली युग्मन को सक्षम कर सकते हैं। इसे लागू करने के लिए आपको एक मध्यस्थ घटक का संदर्भ होना चाहिए जो सभी प्राप्त घटकों को जानता है।

यह "गेम मास्टर को महसूस करता है, कृपया इसे और ऐसा होने दें"

एक सामान्यीकृत पैटर्न प्रकाशित-सदस्यता पैटर्न है। यह उचित है अगर मध्यस्थ में अधिक तर्क नहीं होना चाहिए। अन्यथा एक हाथ से तैयार की गई मध्यस्थ का उपयोग करें जो जानता है कि सभी कॉल को कैसे रूट किया जाए और शायद उन्हें संशोधित भी किया जाए।

सिंक्रोनस और एसिंक्रोनस वेरिएंट हैं जिन्हें आमतौर पर इवेंट बस, संदेश बस या संदेश कतार नाम दिया गया है। वेटर को निर्धारित करने के लिए उन्हें देखें, वे आपके विशेष मामले में उपयुक्त हैं।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.