प्रोग्रामिंग भाषाओं में विरासत को स्वीकार करना


10

मैं अपनी प्रोग्रामिंग भाषा विकसित कर रहा हूं। यह एक सामान्य उद्देश्य की भाषा है (डेस्कटॉप के लिए स्टैटिकली टाइप किए गए पायथन को सोचें, यानी int x = 1;क्लाउड के लिए नहीं)।

क्या आपको लगता है कि विरासत या मिक्सिन्स को अनुमति नहीं देना ठीक है? (यह देखते हुए कि उपयोगकर्ता के पास कम से कम इंटरफेस होगा)

उदाहरण के लिए: Google Go, एक सिस्टम भाषा जिसने वंशानुक्रम की अनुमति नहीं देकर प्रोग्रामिंग समुदाय को झटका दिया।

जवाबों:


4

वास्तव में, हम अधिक से अधिक यह पाते हैं कि वंशानुक्रम का उपयोग उप-इष्टतम है क्योंकि (दूसरों के बीच) यह तंग युग्मन की ओर जाता है।

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

तो हाँ , विशेष रूप से विरासत प्रदान नहीं करना पूरी तरह से वैध है, और बहुत ही प्रचलन डिजाइन निर्णय में है।

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


13

वंशानुक्रम (या कोई एकल विशेषता, वास्तव में) के बारे में तर्क करना आवश्यक है या नहीं, इसके बिना भाषा के बाकी शब्दों पर विचार करना व्यर्थ है; आप शून्य में बहस कर रहे हैं।

आपको एक सुसंगत भाषा डिजाइन दर्शन की आवश्यकता है; भाषा को उन समस्याओं को हल करने में सक्षम होना चाहिए जो इसके लिए डिज़ाइन की गई हैं। इसे प्राप्त करने के लिए मॉडल को विरासत की आवश्यकता हो सकती है या नहीं, लेकिन बड़ी तस्वीर के बिना इसे आंकना मुश्किल है।

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

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

(उल्लिखित दो प्रतिमानों के लिए उदाहरण ढूँढना पाठक के लिए एक अभ्यास के रूप में छोड़ा गया है।)

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


9

हाँ।

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

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

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

इसलिए, सभी ने कहा, मैं इसके लिए जाऊंगा।


2
जब तक आम तौर पर विरासत से जुड़े कार्यों के प्रकार को पूरा करने का एक उचित तरीका है, तब तक आगे बढ़ें। आप कुछ उपयोग के मामलों की कोशिश कर सकते हैं, यह सुनिश्चित करने के लिए (संभवतः यहां तक ​​कि दूसरों से समस्याओं का हल करने के लिए उदाहरण के लिए, आत्म-पूर्वाग्रह से बचने के लिए ...)
आने वाली

नहीं, यह सांख्यिकीय रूप से और दृढ़ता से टाइप किया गया है, मैं शीर्ष पर इसका उल्लेख करूंगा।
क्रिस्टोफर

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

2
कृपया, कृपया, बहुत कृपया, विरासत और कोड के पुन: उपयोग से संबंधित रोकें। यह लंबे समय से ज्ञात है कि कोड के पुन: उपयोग के लिए विरासत वास्तव में खराब उपकरण है।
Jan Hudec

3
कोड के पुन: उपयोग के लिए वंशानुक्रम केवल एक उपकरण है। अक्सर यह एक बहुत अच्छा उपकरण है, और अन्य बार यह भयानक है। वंशानुक्रम पर रचना का उल्लेख करने का मतलब यह नहीं है कि विरासत का उपयोग कभी नहीं किया जाए।
माइकल के

8

हां, यह वंशानुक्रम को छोड़ने के लिए पूरी तरह से उचित डिजाइन निर्णय है।

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

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

यहाँ एक वीडियो है जो मुझे इस सामान्य विषय पर बहुत ज्ञानवर्धक लगा, जहाँ रिच हिकी प्रोग्रामिंग भाषाओं (विरासत सहित) में जटिलता के मूलभूत स्रोतों की पहचान करता है और प्रत्येक के लिए विकल्प प्रस्तुत करता है: सरल बनाया आसान


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

4

जब मैंने पहली बार इस तथ्य पर दौड़ लगाई कि VB6 कक्षाएं वंशानुक्रम (केवल इंटरफेस) का समर्थन नहीं करती हैं, तो इसने मुझे वास्तव में नाराज कर दिया (और अभी भी)।

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

हालांकि मिक्सिंस नहीं हैं? यदि आप एक इंटरफ़ेस लागू करना चाहते हैं और निर्भरता इंजेक्शन के माध्यम से सेट किए गए ऑब्जेक्ट के लिए उस इंटरफ़ेस के सभी काम को सौंपते हैं, तो मिक्सिन आदर्श हैं। अन्यथा आपको हर ऑब्जेक्ट और / या प्रॉपर्टी को चाइल्ड ऑब्जेक्ट को सौंपने के लिए सभी बॉयलरप्लेट कोड लिखना होगा। मैं इसे बहुत करता हूं (C # के लिए धन्यवाद) और यह एक बात है जो मैं चाहता हूं कि मुझे नहीं करना है।


हाँ, जो इस सवाल को प्रेरित करता है वह है SVG DOM का क्रियान्वयन जहाँ कोड का पुन: उपयोग करना बहुत फायदेमंद होता है।
क्रिस्टोफर

2

किसी अन्य उत्तर से असहमत होने के लिए: नहीं, आप सुविधाओं को बाहर फेंकते हैं जब वे उस चीज से असंगत होते हैं जिसे आप अधिक चाहते हैं। जावा (और अन्य GC'd भाषाओं) ने स्पष्ट मेमोरी प्रबंधन को फेंक दिया क्योंकि यह प्रकार की सुरक्षा अधिक चाहता था। हास्केल ने उत्परिवर्तन को बाहर फेंक दिया क्योंकि यह समान तर्क और फैंसी प्रकार अधिक चाहता था। यहां तक ​​कि सी ने कुछ प्रकार के अलियासिंग और अन्य व्यवहार को बाहर कर दिया (या अवैध घोषित कर दिया) क्योंकि यह संकलक अनुकूलन अधिक चाहता था।

तो सवाल यह है: आप विरासत से अधिक क्या चाहते हैं?


1
केवल उस स्पष्ट स्मृति प्रबंधन और प्रकार की सुरक्षा पूरी तरह से असंबंधित है और निश्चित रूप से असंगत नहीं है। वही उत्परिवर्तन और "फैंसी प्रकार" पर लागू होता है। मैं सामान्य तर्क से सहमत हूं लेकिन आपके उदाहरण बुरी तरह से चुने गए हैं।
कोनराड रुडोल्फ

@KonradRudolph, मेमोरी प्रबंधन और प्रकार की सुरक्षा निकट से संबंधित हैं। ए free/ deleteऑपरेशन आपको संदर्भों को अमान्य करने की क्षमता देता है; जब तक आपका प्रकार सिस्टम सभी प्रभावित संदर्भों को ट्रैक करने में सक्षम नहीं होता है, जो भाषा को असुरक्षित बनाता है। विशेष रूप से, न तो C और न ही C ++ सुरक्षित है। यह सच है कि आप उन्हें सहमत करने के लिए एक या दूसरे (जैसे रैखिक प्रकार या आवंटन प्रतिबंध) में समझौता कर सकते हैं। सटीक होने के लिए मुझे कहना चाहिए कि जावा एक विशेष, सरल प्रकार की प्रणाली और अप्रतिबंधित आवंटन के साथ प्रकार की सुरक्षा चाहता था ।
रयान कुल्पेपर

वैसे यह इस बात पर निर्भर करता है कि आप किस प्रकार की सुरक्षा को परिभाषित करते हैं। उदाहरण के लिए, यदि आप संकलन-समय प्रकार की सुरक्षा के लिए (पूरी तरह से उचित) परिभाषा लेते हैं, और संदर्भ अखंडता को आपके प्रकार प्रणाली का हिस्सा बनाना चाहते हैं, तो जावा या तो सुरक्षित नहीं है (क्योंकि यह nullसंदर्भों की अनुमति देता है )। मना freeकरना एक बहुत ही मनमाना अतिरिक्त प्रतिबंध है। सारांश में, भाषा सुरक्षित है या नहीं, यह भाषा की तुलना में आपके प्रकार की सुरक्षा पर निर्भर करता है।
कोनराड रुडोल्फ

1
@ रियान: पॉइंटर्स पूरी तरह से सुरक्षित हैं। वे हमेशा अपनी परिभाषा के अनुसार व्यवहार करते हैं। यह नहीं हो सकता है कि आप उन्हें कैसे पसंद करते हैं, लेकिन यह हमेशा उनके अनुसार कैसे परिभाषित किया जाता है। आप उन्हें कुछ ऐसा करने की कोशिश कर रहे हैं जो वे नहीं हैं। स्मार्ट पॉइंटर्स C ++ में मेमोरी सेफ्टी को काफी मामूली तरीके से गारंटी दे सकते हैं।
डेडएमजैन

@KonradRudolph: जावा में, हर Tसंदर्भ nullया तो एक वर्ग के एक वस्तु या विस्तार का संदर्भ देता है T; nullबदसूरत है, लेकिन nullऊपर के प्रकार को दूषित करने के बजाय एक अच्छी तरह से परिभाषित अपवाद को फेंकने पर ऑपरेशन । C ++ के साथ विरोधाभास: कॉल करने के बाद delete, एक T*पॉइंटर मेमोरी को इंगित कर सकता है जो अब Tऑब्जेक्ट नहीं रखता है । इससे भी बदतर, एक असाइनमेंट में उस पॉइंटर का उपयोग करके एक फ़ील्ड असाइनमेंट करना, आप पूरी तरह से एक अलग वर्ग के ऑब्जेक्ट के क्षेत्र को पूरी तरह से अपडेट कर सकते हैं अगर यह सिर्फ पास के पते पर रखा जाए। यह शब्द की किसी भी उपयोगी परिभाषा से प्रकार की सुरक्षा नहीं है।
रयान कुलपिपर

1

नहीं।

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


8
यह शायद ही सच है: जावा का पूरा डिजाइन ऑपरेटर-ओवरलोडिंग, मल्टीपल इनहेरिटेंस और मैनुअल मेमोरी मैनेजमेंट जैसी सुविधाओं को हटाने के बारे में था। इसके अतिरिक्त, मुझे लगता है कि किसी भी भाषा की विशेषताओं को "पवित्र" मानना ​​गलत है; किसी विशेषता को हटाने के औचित्य के बजाय , आपको इसे जोड़ने का औचित्य सिद्ध करना चाहिए - मैं किसी भी सुविधाओं के बारे में नहीं सोच सकता जो हर भाषा के पास होनी चाहिए।
तिखन जेल्विस

6
@TikhonJelvis: यही कारण है कि जावा एक भयानक भाषा है, और यह "USE GARBAGE-COLLECTED INHERITANCE" को छोड़कर किसी भी चीज की कमी है, यह एक कारण है। भाषा सुविधाओं को उचित ठहराया जाना चाहिए, मैं सहमत हूं, लेकिन यह एक आधार भाषा सुविधा है- इसमें बहुत सारे उपयोगी अनुप्रयोग हैं और प्रोग्रामर द्वारा DRY का उल्लंघन किए बिना इसे दोहराया नहीं जा सकता है।
1

1
@DeadMG वाह! बहुत मजबूत भाषा।
क्रिस्टोफर

@DeadMG: मैंने एक टिप्पणी के रूप में एक खंडन लिखना शुरू कर दिया, लेकिन फिर मैंने इसे एक उत्तर (qv) में बदल दिया।
रयान क्यूलपेपर

1
"पूर्णता तब प्राप्त होती है जब जोड़ने के लिए कुछ भी नहीं बचता है लेकिन जब हटाने के लिए कुछ नहीं बचता है" (q)
9000

1

कड़ाई से सी + + बोलने वाले से बोलते हुए, विरासत दो मुख्य उद्देश्यों के लिए उपयोगी है:

  1. यह कोड पुनर्जीवन की अनुमति देता है
  2. चाइल्ड क्लास में ओवरराइडिंग के साथ संयोजन में, यह आपको अपने प्रकार को जाने बिना एक चाइल्ड क्लास ऑब्जेक्ट को संभालने के लिए बेस क्लास पॉइंटर का उपयोग करने की अनुमति देता है।

बिंदु 1 के लिए जब तक आपके पास बहुत अधिक कलाबाजी में लिप्त होने के बिना कोड साझा करने का कोई तरीका है, आप विरासत के साथ दूर कर सकते हैं। बिंदु 2 के लिए। आप जावा के रास्ते पर जा सकते हैं और इस सुविधा को लागू करने के लिए इंटरफ़ेस पर जोर दे सकते हैं।

वंशानुक्रम हटाने का लाभ है

  1. लंबी पदानुक्रम और इससे जुड़ी समस्याओं को रोकें। आपका कोड-साझाकरण तंत्र इसके लिए पर्याप्त होना चाहिए।
  2. बच्चे की कक्षाएं तोड़ने से माता-पिता की कक्षाओं में परिवर्तन से बचें।

यह व्यापार मुख्यतः "डॉन्ट रिपीट योरसेल्फ" और एक तरफ लचीलेपन और दूसरी तरफ समस्या-परिहार के बीच होता है। व्यक्तिगत रूप से मुझे विरासत से देखने से नफरत होगी C ++ से जाना बस कुछ अन्य डेवलपर को समस्याएँ दूर करने के लिए पर्याप्त स्मार्ट नहीं हो सकता है।


1

क्या आपको लगता है कि विरासत या मिक्सिन्स को अनुमति नहीं देना ठीक है? (यह देखते हुए कि उपयोगकर्ता के पास कम से कम इंटरफेस होगा)

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

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

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