क्या मुझे गेम विकसित करने के लिए ऑब्जेक्ट इनहेरिटेंस का उपयोग करने से बचना चाहिए?


36

मैं एकता के साथ खेल विकसित करते समय OOP सुविधाओं को पसंद करता हूं। मैं आमतौर पर एक आधार वर्ग (ज्यादातर अमूर्त) बनाता हूं और विभिन्न अन्य वस्तुओं के समान कार्यक्षमता साझा करने के लिए ऑब्जेक्ट इनहेरिटेंस का उपयोग करता हूं।

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

मैं एक अमूर्त आधार वर्ग का उपयोग कर रहा हूँ, जैसे कुछ WeaponBaseऔर विशिष्ट हथियार वर्ग बनाना Shotgun, जैसे AssaultRifle, Machinegunकुछ ऐसा। बहुत सारे फायदे हैं, और एक पैटर्न जो मुझे बहुत पसंद है वह है बहुरूपता। मैं उपवर्गों द्वारा बनाई गई वस्तु का इलाज कर सकता हूं जैसे कि वे आधार वर्ग थे, ताकि तर्क को काफी कम किया जा सके और अधिक पुन: प्रयोज्य बनाया जा सके। यदि मुझे उप-वर्ग के क्षेत्रों या विधियों तक पहुंचने की आवश्यकता है, तो मैं वापस उप-वर्ग में जाता हूं।

मैं एक ही क्षेत्रों, आमतौर पर विभिन्न वर्गों में इस्तेमाल परिभाषित करने के लिए नहीं करना चाहते हैं की तरह AudioSource/ Rigidbody/ Animatorऔर सदस्य खेतों मैं की तरह परिभाषित के बहुत सारे fireRate, damage, range, spreadऔर इतने पर। इसके अलावा कुछ मामलों में, कुछ तरीकों को अधिलेखित किया जा सकता है। तो मैं उस मामले में आभासी तरीकों का उपयोग कर रहा हूं, ताकि मूल रूप से मैं मूल विधि से विधि का उपयोग करके उस पद्धति को लागू कर सकूं, लेकिन अगर तर्क बच्चे में अलग होना चाहिए, तो मैंने उन्हें मैन्युअल रूप से ओवरराइड कर दिया है।

तो, क्या इन सभी चीजों को बुरी प्रथाओं के रूप में छोड़ दिया जाना चाहिए? क्या मुझे इसके बजाय इंटरफेस का उपयोग करना चाहिए?


30
"बहुत सारे फायदे हैं, और एक पैटर्न जो मुझे बहुत पसंद है वह है बहुरूपता।" बहुरूपता एक पैटर्न नहीं है। यह सचमुच OOP का पूरा बिंदु है। अन्य चीजें जैसे सामान्य क्षेत्र आदि को आसानी से बिना कोड डुप्लीकेशन या विरासत के प्राप्त किया जा सकता है।
घन

3
क्या जिस व्यक्ति ने आपको सुझाव दिया है कि आप विरासत से बेहतर थे, क्या आप कोई तर्क देते हैं? मैं उत्सुक हूँ।
हॉकर 65

1
@ क्यूबिक मैंने कभी नहीं कहा कि बहुरूपता एक पैटर्न है। मैंने कहा "... एक पैटर्न जो मुझे बहुत पसंद है वह है बहुरूपता"। इसका मतलब है कि जिस पैटर्न का मैं वास्तव में आनंद लेता हूं वह "बहुरूपता" का उपयोग कर रहा है, न कि बहुरूपता एक पैटर्न है।
मॉडर्नेटर

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

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

जवाबों:


65

अपनी इकाई और सूची / मद प्रणालियों में विरासत पर अनुकूल रचना । यह सलाह खेल तर्क संरचनाओं पर लागू होती है, जब आप जिस तरह से जटिल चीजों को इकट्ठा कर सकते हैं (रनटाइम पर) बहुत सारे विभिन्न संयोजनों को जन्म दे सकता है; जब हम रचना पसंद करते हैं।

अपने एप्लिकेशन-स्तरीय तर्क में रचना पर अनुकूल वंशानुक्रम , UI से सब कुछ सेवाओं का निर्माण करता है। उदाहरण के लिए,

Widget->Button->SpinnerButton या

ConnectionManager->TCPConnectionManagerबनाम ->UDPConnectionManager

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

नीचे पंक्ति : जहाँ आप कर सकते हैं विरासत का उपयोग करें, लेकिन रचना का उपयोग करें जहाँ आपको होना चाहिए। PS अन्य कारण जो हम इकाई प्रणालियों में रचना का पक्ष ले सकते हैं, वह यह है कि आमतौर पर कई संस्थाएं हैं, और विरासत में प्रत्येक वस्तु पर सदस्यों तक पहुंचने के लिए एक प्रदर्शन लागत हो सकती है; vtables देखें ।


10
वंशानुक्रम का अर्थ यह नहीं है कि सभी विधियाँ आभासी होंगी। तो यह स्वचालित रूप से एक प्रदर्शन लागत के लिए नेतृत्व नहीं करता है। VTable केवल वर्चुअल कॉल भेजने में भूमिका निभाता है , डेटा सदस्यों तक पहुँचने में नहीं।
रुस्लान

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

7
P.S. The other reason we may favour composition in entity systems is ... performance: क्या यह वास्तव में सच है? @ लिनिथ शो द्वारा लिंक किए गए WIkipedia पेज को देखते हुए, कि आपको अपने ऑब्जेक्ट को इंटरफेस की रचना करने की आवश्यकता होगी। इसलिए आपके पास (अभी या इससे भी अधिक) वर्चुअल फ़ंक्शन कॉल और अधिक कैश मिस हैं, जैसा कि आपने परोक्ष रूप से एक और स्तर पेश किया है।
फ्लेमफायर

1
@Flamefire हाँ, यह सच है; आपके डेटा को व्यवस्थित करने के तरीके हैं जैसे कि आपकी कैश दक्षता इष्टतम है, भले ही, और निश्चित रूप से कहीं अधिक इष्टतम है कि उन अतिरिक्त अप्रत्यक्ष। ये नहीं हैं विरासत और कर रहे हैं , रचना सरणी के- struct / struct के- सरणियों अर्थों में अधिक अलग विन्यास में, (interleaved / गैर interleaved कैश रेखीय व्यवस्था में डेटा), तेज और कभी कभी डेटा सेट से मेल करने के डुप्लिकेट यद्यपि अपनी पाइपलाइन के विभिन्न भागों में परिचालन का। लेकिन एक बार फिर, यहां जाने के लिए एक बहुत बड़ा मोड़ होगा जो कि छुपाने के लिए सबसे अच्छा है।
इंजीनियर

2
कृपया स्पष्टीकरण या समालोचना के लिए नागरिक अनुरोधों पर टिप्पणी रखने और विचारों की सामग्री पर बहस करने के लिए याद रखें, न कि उन्हें बताने वाले व्यक्ति के चरित्र या अनुभव ।
जोश

18

आपको पहले से ही कुछ अच्छे जवाब मिले हैं, लेकिन आपके सवाल में कमरे का विशाल हाथी यह है:

किसी से सुना है कि विरासत का उपयोग करने से बचना चाहिए, और हमें इसके बजाय इंटरफेस का उपयोग करना चाहिए

अंगूठे के नियम के रूप में, जब कोई आपको अंगूठे का नियम देता है, तो इसे अनदेखा करें। यह न केवल "किसी को आपको कुछ बताने" के लिए जाता है, बल्कि इंटरनेट पर सामान पढ़ने के लिए भी जाता है। जब तक आप नहीं जानते कि क्यों (और वास्तव में इसके पीछे खड़े हो सकते हैं), ऐसी सलाह बेकार है और अक्सर बहुत हानिकारक होती है।

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

कम युग्मन

इसका मतलब यह है कि आपके कोड में किसी भी "सामान का बंडल" अपने परिवेश पर जितना संभव हो उतना कम निर्भर होना चाहिए। यह कक्षाओं (वर्ग डिजाइन) लेकिन वस्तुओं (वास्तविक कार्यान्वयन), सामान्य रूप से "फाइलें" (यानी, #includeप्रति एकल .cppफ़ाइल की संख्या, importप्रति .javaफ़ाइल की संख्या और इतने पर) के लिए जाती है।

एक संकेत है कि दो संस्थाएं युग्मित हैं, उनमें से एक टूट जाएगा (या बदलने की आवश्यकता है) जब दूसरे को किसी भी तरह से बदल दिया जाता है।

विरासत में युग्मन बढ़ता है, जाहिर है; बेस क्लास बदलने से सभी उपवर्ग बदल जाते हैं।

इंटरफेस युग्मन को कम करते हैं: एक स्पष्ट, विधि-आधारित अनुबंध को परिभाषित करके, आप इंटरफ़ेस के दोनों किनारों के बारे में कुछ भी स्वतंत्र रूप से बदल सकते हैं, जब तक कि आप अनुबंध को नहीं बदलते। (ध्यान दें कि "इंटरफ़ेस" एक सामान्य अवधारणा है, जावा interfaceया सी ++ सार कक्षाएं केवल कार्यान्वयन विवरण हैं)।

उच्च सामंजस्य

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

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

एक संकेत है कि एक इकाई सामंजस्यपूर्ण नहीं है यदि यह बड़ा और बड़ा हो जाता है, तो एक ही समय में कई दिशाओं में शाखाकरण होता है।

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

इंटरफेस के दो पक्षों के बीच जिम्मेदारियों को स्पष्ट रूप से विभाजित करके अंतर अप्रत्यक्ष रूप से सामंजस्य बढ़ाते हैं।

अब क्या करे

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

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


विस्तृत विवरण के लिए धन्यवाद। यह समझने में मददगार है कि मैं क्या याद कर रहा हूं।
मॉर्डनेटर

13

यह विचार कि विरासत से बचना चाहिए बस गलत है।

इसमें एक कोडिंग सिद्धांत मौजूद है जिसे रचना से अधिक वंशानुक्रम कहा जाता है । यह कहता है कि आप रचना के साथ समान चीजें हासिल कर सकते हैं, और यह बेहतर है, क्योंकि आप कुछ कोड का पुन: उपयोग कर सकते हैं। देखें कि मुझे विरासत पर रचना क्यों पसंद करनी चाहिए?

मुझे कहना है कि मुझे आपके हथियार वर्ग पसंद हैं और क्या यह उसी तरह होगा। लेकिन मैंने अब तक एक खेल नहीं बनाया है ...

जैसा कि जेम्स ट्रॉटर द्वारा बताया गया है, रचना में कुछ फायदे हो सकते हैं, खासकर रनटाइम में लचीलेपन में यह बदलने के लिए कि हथियार कैसे काम करता है। यह विरासत के साथ संभव होगा, लेकिन यह अधिक कठिन है।


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

3
@JamesTrotter इस बिंदु पर, मैं बॉर्डरलैंड्स और इसकी बंदूकों के बारे में सोचता हूं, और सोचता हूं कि यह केवल एक विरासत के साथ क्या होगा ...
बाल्ड्रिक

1
@JamesTrotter काश कि एक उत्तर होता और एक टिप्पणी नहीं होती।
फराप जूल

6

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

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

एक ग्रेनेडलंचर के साथ एक असॉल्ट राइफल के बारे में क्या है - हम्म, थोड़ा मुश्किल। क्या आप ग्रेनेडलंचर को रात के शिकार के लिए टॉर्च के साथ बदल सकते हैं?

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

एकाधिक वंशानुक्रम इन तुच्छ उदाहरणों में से कुछ को ठीक कर सकते हैं, लेकिन यह कहते हैं कि यह समस्याओं का एक सेट है।

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


2
"आप अपने उपयोगकर्ता को एक कॉन्फ़िगर फ़ाइल को संपादित करके पूर्ववर्ती बंदूकें बनाने की अनुमति कैसे देते हैं?" -> पैटर्न मैं आमतौर पर प्रत्येक हथियार के लिए एक अंतिम वर्ग बनाता हूं। उदाहरण के लिए, Glock17 की तरह। सबसे पहले WeaponBase क्लास बनाएं। यह वर्ग अमूर्त है, फायर मोड, फायर रेट, पत्रिका आकार, अधिकतम बारूद, छर्रों जैसे सामान्य मूल्यों को परिभाषित करता है। इसके अलावा यह यूजर इनपुट को भी संभालता है, जैसे कि माउस 1 / माउस 2 / रीलोड और इनवॉइस कॉरपोरेशन मेथड। वे लगभग आभासी हैं, या अधिक कार्यों के लिए विभाजित हैं ताकि डेवलपर आधार कार्यक्षमता को ओवरराइड कर सकें यदि उन्हें आवश्यकता हो। और फिर एक और वर्ग बनाएं जिसने वेपनबेस को बढ़ाया,
आधुनिकतावादी

2
SlideStoppableWeapon की तरह कुछ। अधिकांश पिस्तौल में यह होता है, और यह अतिरिक्त व्यवहार को संभालता है जैसे स्लाइड बंद हो गया। अंत में Glock17 क्लास बनाएं जो SlideStoppableWeapon से फैली हुई है। Glock17 अंतिम वर्ग है, अगर बंदूक में अद्वितीय क्षमता है, जो अंत में केवल यहां लिखी गई है। मैं आमतौर पर इस पैटर्न का उपयोग करता हूं जब बंदूक में विशेष अग्नि तंत्र या पुनः लोड तंत्र होता है। कक्षा पदानुक्रम के अंत के लिए उस अद्वितीय व्यवहार को लागू करें, माता-पिता से जितना संभव हो उतना सामान्य लॉजिक्स को मिलाएं।
आधुनिकतावादी

2
@modernator जैसा कि मैंने कहा, यह सिर्फ एक दिशानिर्देश है - यदि आप इस पर भरोसा नहीं करते हैं, तो इसे अनदेखा करने के लिए स्वतंत्र महसूस करें, बस समय के साथ परिणाम के रूप में अपनी आँखें खुली रखें और लाभ का मूल्यांकन करें। मैं उन जगहों को याद करने की कोशिश करता हूं जिन्हें मैंने अपने पैर की उंगलियों से टकराया था और दूसरों को भी इससे बचने में मदद करता हूं, लेकिन मेरे लिए जो काम करता है वह आपके लिए काम नहीं कर सकता है।
Bill K

7
@modernator Minecraft में उन्होंने Monsterएक उपवर्ग बनाया WalkingEntity। फिर उन्होंने स्लैम जोड़ दिए। कितना अच्छा लगता है कि आपने काम किया है?
user253751

1
@immibis क्या आपके पास उस समस्या का संदर्भ या विशेष लिंक है? Googling minecraft कीवर्ड मुझे वीडियो लिंक में डुबो देता है ;-)
पीटर - मोनिक

3

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

इंटरफेस किसी भी ओओपी भाषा के प्रथम श्रेणी के नागरिक हैं। कक्षाएं माध्यमिक कार्यान्वयन विवरण हैं। नए प्रोग्रामर्स का दिमाग शिक्षकों और पुस्तकों द्वारा गंभीर रूप से विकृत है जो इंटरफेस से पहले कक्षाएं और विरासत का परिचय देते हैं।

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


यदि इंटरफेस किसी भी ओओपी भाषा के प्रथम श्रेणी के नागरिक हैं तो मैं सोच रहा था कि क्या पायथन, रूबी, ... ओओपी भाषा नहीं हैं।
ब्लैकजैक

@ ब्लेकजैक: रूबी में, इंटरफ़ेस निहित है (यदि आप चाहते हैं तो बतख टाइपिंग), और विरासत के बजाय रचना का उपयोग करके व्यक्त किया जाता है (साथ ही, इसमें मिक्सिंस हैं जो बीच में कहीं हैं, जहां तक ​​मेरा संबंध है ...)
AnoE

@BlackJack "इंटरफ़ेस" (अवधारणा) की आवश्यकता नहीं है interface(भाषा कीवर्ड)।
कैलथ

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

2

जब भी कोई आपको बताता है कि सभी मामलों के लिए एक विशिष्ट दृष्टिकोण सबसे अच्छा है, तो यह वही है जो आपको बता रहा है कि एक और एक ही दवा सभी रोगों को ठीक करती है।

विरासत बनाम रचना एक है-एक बनाम एक है-एक सवाल है। इंटरफेस अभी तक एक और (3 जी) तरीका है, कुछ स्थितियों के लिए उपयुक्त है।

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

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

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

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

क्लास फॉक्स, जाहिर है, उड़ नहीं सकता। इसलिए यदि आप पूर्वजों को सभी विशेषताओं के लिए परिभाषित करते हैं, तो आप वंश को ठीक से प्राप्त नहीं कर सकते।

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

इन तरीकों में से प्रत्येक में ऐसे मामलों का उपयोग होता है जब यह सबसे अच्छा होता है, कोई भी दृष्टिकोण सभी मामलों के लिए एक सबसे अच्छा समाधान नहीं होता है।


1

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

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

लेकिन इसका मतलब यह नहीं है कि, आपके वॉल्यूमेट्रिक क्लाउड कार्यान्वयन का कहना है, आपको विरासत का उपयोग नहीं करना चाहिए। उस कोड के लिए पर्याप्त हो सकता है और कई वर्गों से मिलकर बनता है, और आप इसके लिए आवश्यकतानुसार OOP का उपयोग कर सकते हैं। लेकिन यह सभी एक एकल खेल घटक के लिए राशि होगी।

एक साइड नोट के रूप में, मैं इसके साथ कुछ समस्या लेता हूं:

मैं आमतौर पर एक आधार वर्ग (ज्यादातर अमूर्त) बनाता हूं और विभिन्न अन्य वस्तुओं के समान कार्यक्षमता साझा करने के लिए ऑब्जेक्ट इनहेरिटेंस का उपयोग करता हूं।

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

यदि आप चाहते हैं, तो आप इंटरफेस का उपयोग कर सकते हैं, कह सकते हैं कि List<IWeapon>इसमें विभिन्न प्रकार के हथियार हैं। इस तरह, आप सभी हथियार के लिए IWeapon इंटरफ़ेस, और MonoBehaviour उपवर्ग दोनों से विरासत में प्राप्त कर सकते हैं, और कई विरासत के अभाव के साथ किसी भी मुद्दे से बच सकते हैं।


-3

आपको समझ में नहीं आ रहा है कि इंटरफ़ेस क्या है या क्या करता है। मुझे ओओ के बारे में सोचने के बारे में 10+ साल लगे और कुछ वास्तव में स्मार्ट लोगों से सवाल पूछने से मुझे इंटरफेस के साथ आह-हा करने में मदद मिली। उम्मीद है की यह मदद करेगा।

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

एक ही सादृश्य दुनिया के साथ अंतर करने वाले व्यक्ति (शरीर और आत्मा) के बीच इस्तेमाल किया जा सकता है। शरीर मन और दुनिया के बीच का इंटरफेस है। हर कोई दुनिया में एक ही तरह से हस्तक्षेप करता है, एकमात्र विशिष्टता यह है कि हम दुनिया के साथ कैसे बातचीत करते हैं, यही है कि हम अपने MIND को DECIDE HOW we इंटरफ़ेस / इंटरएक्ट का उपयोग कैसे करते हैं।

एक इंटरफेस तो बस एक OO संरचना के साथ एक अलग ओओ संरचना के साथ प्रत्येक पक्ष से संबंधित एक तंत्र है जिसमें अलग-अलग विशेषताएँ होती हैं जो एक दूसरे माध्यम / पर्यावरण में कुछ कार्यात्मक उत्पादन करने के लिए एक दूसरे से बातचीत / नक्शा करना चाहिए।

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

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