वर्ग-आधारित OOP पर प्रोटोटाइप-आधारित OOP के क्या लाभ हैं?


47

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

  1. प्रोटोटाइप-आधारित ओओपी का उपयोग करने के लिए संरचनात्मक लाभ क्या हैं, यदि कोई हो? (उदाहरण के लिए क्या हम इसे कुछ अनुप्रयोगों में तीव्र या कम स्मृति गहन होने की उम्मीद करेंगे?)
  2. कोडर के दृष्टिकोण से क्या फायदे हैं? (जैसे कि कुछ अनुप्रयोगों को कोड करना या प्रोटोटाइपिंग का उपयोग करके अन्य लोगों के कोड का विस्तार करना आसान है?)

कृपया इस प्रश्न को विशेष रूप से जावास्क्रिप्ट के बारे में एक प्रश्न के रूप में न देखें (जो कि वर्षों से कई दोष हैं जो पूरी तरह से प्रोटोटाइप के लिए असंबंधित हैं)। इसके बजाय, कृपया इसे कक्षाओं बनाम प्रोटोटाइप के सैद्धांतिक लाभों के संदर्भ में देखें।

धन्यवाद।


जवाबों:


46

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

स्रोत कोड यदि आप रुचि रखते हैं ( तानाशाह - जावा रोगेलिक )

यहाँ मुख्य लाभ हैं:

  • यह नया "कक्षाएं" बनाने के लिए तुच्छ है - बस प्रोटोटाइप की नकल करें और गुणों और वॉइला के एक जोड़े को बदल दें ... नया वर्ग। मैंने इसका उपयोग जावा के 3-6 लाइनों में उदाहरण के लिए नए प्रकार के पोशन को परिभाषित करने के लिए किया। बॉयलरप्लेट की नई श्रेणी की फ़ाइल और भार से बहुत बेहतर!
  • तुलनात्मक रूप से छोटे कोड के साथ "बड़ी संख्या में" वर्गों का निर्माण और रखरखाव करना संभव है - उदाहरण के लिए तानाशाह के पास कोड के लगभग 42,000 लाइनों के साथ 3000 विभिन्न प्रोटोटाइप जैसे कुछ थे। यह जावा के लिए बहुत अद्भुत है!
  • मल्टीपल इनहेरिटेंस आसान है - आप सिर्फ एक प्रोटोटाइप से गुणों का एक सबसेट कॉपी करते हैं और उन्हें दूसरे प्रोटोटाइप में गुणों पर चिपकाते हैं। उदाहरण के लिए एक आरपीजी में, आप "स्टील ऑब्जेक्ट" के गुणों में से कुछ और "गोलेम" के गुणों में से कुछ और एक "अनजाने राक्षस" के गुणों में से कुछ के लिए "स्टील गोलेम" चाह सकते हैं। प्रोटोटाइप के साथ आसान, एक विरासत वारिस के साथ ऐसा करने की कोशिश करें ......
  • आप संपत्ति संशोधक के साथ चतुर चीजें कर सकते हैं - जेनेरिक "रीड प्रॉपर्टी" विधि में चतुर तर्क रखकर, आप विभिन्न संशोधक लागू कर सकते हैं। उदाहरण के लिए, एक जादुई अंगूठी को परिभाषित करना आसान था जिसने +2 शक्ति को जोड़ा था जिसने भी इसे पहना था। इस के लिए तर्क अंगूठी वस्तु में था, नहीं , "पढ़ने शक्ति" विधि में तो आप अपने कोड बेस में कहीं सशर्त परीक्षण के बहुत सारे डाल करने के लिए होने से बचा (उदाहरण के लिए "चरित्र शक्ति में वृद्धि का एक अंगूठी पहन रखी है?")
  • उदाहरण अन्य उदाहरणों के लिए टेम्पलेट बन सकते हैं - जैसे यदि आप किसी ऑब्जेक्ट को "क्लोन" करना चाहते हैं तो यह आसान है, बस नई ऑब्जेक्ट के लिए प्रोटोटाइप के रूप में मौजूदा ऑब्जेक्ट का उपयोग करें। विभिन्न वर्गों के लिए बहुत सारे जटिल क्लोनिंग तर्क लिखने की आवश्यकता नहीं है।
  • रनटाइम पर व्यवहार को बदलना काफी आसान है - यानी आप एक गुण और "मॉर्फ" को रनटाइम पर बहुत अधिक मनमाने ढंग से बदल सकते हैं। इन-गेम प्रभावों को शांत करने की अनुमति देता है, और यदि आप इसे "स्क्रिप्टिंग भाषा" के साथ जोड़ते हैं, तो रनटाइम में बहुत कुछ संभव है।
  • यह प्रोग्रामिंग की "कार्यात्मक" शैली के लिए अधिक अनुकूल है - आप अपने आप को बहुत सारे कार्यों को लिखने के लिए ढूंढते हैं जो वस्तुओं को एक अधिनियम के अनुसार उचित विश्लेषण करते हैं, बजाय विशिष्ट वर्गों से जुड़े तरीकों में एम्बेडेड तर्क के। मैं व्यक्तिगत रूप से इस एफपी शैली को पसंद करता हूं।

यहाँ मुख्य कमियां हैं:

  • आप स्थैतिक टाइपिंग का आश्वासन खो देते हैं - चूंकि आप प्रभावी रूप से एक गतिशील ऑब्जेक्ट सिस्टम बना रहे हैं। इसका मतलब यह है कि आपको यह सुनिश्चित करने के लिए अधिक परीक्षण लिखने की ज़रूरत है कि व्यवहार सही है और ऑब्जेक्ट सही "तरह" के हैं
  • कुछ प्रदर्शन ओवरहेड हैं - चूंकि ऑब्जेक्ट गुणों के रीड को आमतौर पर एक या एक से अधिक मैप लुकअप के माध्यम से जाने के लिए मजबूर किया जाता है, आप प्रदर्शन के मामले में थोड़ी लागत का भुगतान करते हैं। मेरे मामले में यह कोई समस्या नहीं थी, लेकिन यह कुछ मामलों में एक समस्या हो सकती है (उदाहरण के लिए एक 3D FPS जिसमें बहुत सी वस्तुओं को हर फ्रेम में समेटा जा रहा है)
  • Refactorings उसी तरह से काम नहीं करते हैं - एक प्रोटोटाइप आधारित प्रणाली में आप अनिवार्य रूप से कोड के साथ अपने उत्तराधिकार उत्तराधिकार का "निर्माण" कर रहे हैं। आईडीई / रिफैक्टरिंग उपकरण वास्तव में आपकी मदद नहीं कर सकते हैं क्योंकि वे आपके दृष्टिकोण को कम नहीं कर सकते हैं। मुझे यह कभी भी समस्या नहीं लगी, लेकिन अगर आप सावधान नहीं हैं तो यह हाथ से निकल सकता है। आप शायद यह जांचना चाहते हैं कि आपके वंशानुगत पदानुक्रम का निर्माण सही ढंग से हो रहा है या नहीं!
  • यह थोड़ा अलग-थलग है - एक पारंपरिक ओओपी शैली के लिए उपयोग किए जाने वाले लोग आसानी से भ्रमित हो सकते हैं। "तुम्हारा क्या मतलब है" थिंग "नामक केवल एक वर्ग है?" - "मैं इस अंतिम थिंग क्लास का विस्तार कैसे करूं?" - "आप ओओपी सिद्धांतों का उल्लंघन कर रहे हैं !!!" - "किसी भी तरह की वस्तु पर कार्य करने वाले इन सभी स्थिर कार्यों को गलत कहना गलत है?"

अंत में कुछ कार्यान्वयन नोट:

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


(+1) इसका अच्छा विश्लेषण है। कुल मिलाकर, इसके जावा मॉडल में आधारित, उदाहरण के लिए, डेल्फी, सी #, वीबीनेट में स्पष्ट गुण हैं।
umlcat

3
@umlcat - मुझे लगता है कि जावा मॉडल डेल्फी / सी # मॉडल (प्रॉपर्टी एक्सेस के लिए अच्छी सिंथैटिक शुगर के अलावा) के समान है - आपको अभी भी उन गुणों को घोषित करना होगा जो आप अपनी कक्षा की परिभाषा में चाहते हैं। एक प्रोटोटाइप मॉडल की बात यह है कि यह परिभाषा स्थिर नहीं है और आपको पहले से कोई घोषणा करने की आवश्यकता नहीं है ....
mikera

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

एकाधिक वंशानुक्रम के आसान होने के संबंध में, आपने इसकी तुलना जावा से की है, जो एकाधिक वंशानुक्रम का समर्थन नहीं करता है, लेकिन क्या यह उन भाषाओं की तुलना में आसान है, जो इसे C ++ का समर्थन करती हैं?
पियोवेज़न

2

प्रोटोटाइप आधारित OOP का मुख्य लाभ यह है कि वस्तुओं और "कक्षाओं" को रनटाइम पर बढ़ाया जा सकता है।

क्लास-आधारित OOP में, कई अच्छी विशेषताएं हैं, दुर्भाग्य से, यह प्रोग्रामिंग भाषा पर निर्भर करता है।

ऑब्जेक्ट पास्कल (डेल्फी), VB.Net & C # में गुणों का उपयोग करने का एक बहुत ही सीधा तरीका है (खेतों के साथ भ्रमित नहीं होना) और गुणों की पहुंच विधि, जबकि जावा और सी ++, गुणों को विधियों द्वारा एक्सेस किया जाता है। और PHP में दोनों का मिश्रण है, जिसे "जादू के तरीके" कहा जाता है।

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


0

मुझे @umlcat से सहमत होना होगा। कक्षा विस्तार एक प्रमुख लाभ है। उदाहरण के लिए, मान लीजिए कि आप एक लंबी अवधि में एक स्ट्रिंग कक्षा में अधिक कार्यक्षमता जोड़ना चाहते हैं। C ++ में आप पिछली स्ट्रिंग क्लास पीढ़ियों की निरंतर विरासत के माध्यम से ऐसा करेंगे। इस दृष्टिकोण के साथ समस्या यह है कि प्रत्येक पीढ़ी अनिवार्य रूप से इसका एक अलग प्रकार बन जाता है जो मौजूदा कोड आधारों के बड़े पैमाने पर पुनर्लेखन का कारण बन सकता है। प्रोटोटाइपिकल इनहेरिटेंस के साथ आप मूल आधार वर्ग के लिए बस एक नई विधि 'संलग्न' करते हैं ..., हर जगह विरासत में मिले वर्गों और वंशानुगत संबंधों का कोई व्यापक निर्माण नहीं होता है। मैं C ++ को उनके नए मानक में एक समान विस्तार तंत्र के साथ देखना पसंद करूंगा। लेकिन उनकी समिति उन लोगों द्वारा चलाई जाती है जो आकर्षक और लोकप्रिय सुविधाओं को जोड़ना चाहते हैं।


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