"वंशानुक्रम पर अनुकूल रचना" की यह अवधारणा कहाँ से आती है?


143

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

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

क्या किसी को पता है कि यह अवधारणा कहां से आती है, और इसके पीछे तर्क क्या है?


45
जैसा कि दूसरों ने बताया है, यह एक लंबे समय के आसपास रहा है - मुझे आश्चर्य है कि आप अभी इसे सुन रहे हैं। यह किसी भी व्यक्ति के लिए सहज है जो जावा जैसी भाषाओं में किसी भी समय बड़ी प्रणाली का निर्माण कर रहा है। यह मेरे द्वारा दिए गए किसी भी साक्षात्कार के लिए मुख्य है और जब कोई उम्मीदवार विरासत के बारे में बात करना शुरू करता है, तो मुझे उनके कौशल स्तर और अनुभव की मात्रा पर संदेह करना शुरू हो जाता है। यहाँ एक अच्छा परिचय है कि वंशानुक्रम क्यों भंगुर समाधान है (कई अन्य लोग हैं): artima.com/lejava/articles/designprinciples4.html
Janx

6
@ जेनएक्स: शायद यह बात है। मैं जावा जैसी भाषाओं में बड़े सिस्टम का निर्माण नहीं करता हूं; मैं उन्हें डेल्फी में बनाता हूं, और लिस्कोव प्रतिस्थापन और बहुरूपता के बिना हमें कभी भी कुछ नहीं मिलेगा। इसका ऑब्जेक्ट मॉडल कुछ हद तक जावा या सी ++ की तुलना में अलग है, और बहुत सी समस्याएं जो इस मैक्सिम को हल करने के लिए प्रतीत होती हैं, वास्तव में मौजूद नहीं हैं, या डेल्फी में बहुत कम समस्याग्रस्त हैं। मुझे लगता है कि विभिन्न दृष्टिकोणों से अलग दृष्टिकोण।
मेसन व्हीलर

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

8
पिछले कुछ महीने?
जस

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

जवाबों:


136

हालांकि मुझे लगता है कि मैंने रचना-बनाम-वंशानुक्रम चर्चा को गोफ से बहुत पहले सुना है, मैं अपनी उंगली किसी विशिष्ट स्रोत पर नहीं डाल सकता। वैसे भी बूच रहा होगा।

<शेख़ी>

आह, लेकिन कई मंत्रों की तरह, यह एक विशिष्ट लाइनों के साथ पतित है:

  1. यह एक अच्छी तरह से सम्मानित स्रोत द्वारा एक विस्तृत विवरण और तर्क के साथ पेश किया जाता है जो मूल जटिल चर्चा के अनुस्मारक के रूप में कैच-वाक्यांश को सिक्के देता है।
  2. इसे कुछ समय के लिए कुछ-कुछ-जानने वाले क्लब विंक के साथ साझा किया जाता है, आमतौर पर जब n00b गलतियों पर टिप्पणी की जाती है
  3. जल्द ही इसे हजारों लोगों ने बिना सोचे समझे दोहराया है, जिन्होंने कभी स्पष्टीकरण नहीं पढ़ा, लेकिन इसे एक बहाने के रूप में इस्तेमाल करते हैं , न कि एक बहाने के रूप में, और दूसरों से बेहतर महसूस करने के लिए एक सस्ते और आसान तरीके के रूप में।
  4. अंततः, उचित डिबंकिंग की कोई भी राशि "मेम" ज्वार को नहीं रोक सकती है - और प्रतिमान धर्म और हठधर्मिता में पतित हो जाता है।

मूल रूप से, ज्ञान के लिए n00bs का नेतृत्व करने के लिए अभिप्रेत है, अब उन्हें बेहोश करने के लिए एक क्लब के रूप में प्रयोग किया जाता है।

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

कृपया अपने डिज़ाइन के बारे में सोचें , और नारे लगाना बंद करें।

</ शेख़ी>


16
बूच का तर्क है कि कार्यान्वयन विरासत वर्गों के बीच उच्च युग्मन का परिचय देती है। दूसरी ओर, वह विरासत को मुख्य अवधारणा मानता है जो OOP को प्रक्रियात्मक प्रोग्रामिंग से अलग करता है।
नेमनजा ट्रिफ़ुनोविक

13
इस तरह की बात के लिए एक शब्द होना चाहिए। शीघ्रपतन , हो सकता है?
जोर्ग डब्ल्यू मित्तग

8
@ Jörg: आप जानते हैं कि प्रीमेच्योर रिगर्जेशन जैसे शब्द का क्या होगा? ठीक ऊपर जो बताया गया है। :) (Btw। जब प्रतिगमन कभी समय से पहले नहीं होता है?)
Bjarke Freund-Hansen

6
@ नेमंजा: सही है। सवाल यह है कि क्या यह कपलिंग वास्तव में खराब है। यदि कक्षाएं अवधारणात्मक रूप से दृढ़ता से युग्मित होती हैं और वैचारिक रूप से एक सुपर-टाइप-उपप्रकार संबंध बनाती हैं, और कभी भी गर्भधारण नहीं किया जा सकता है, भले ही वे भाषा के स्तर पर औपचारिक रूप से डिकौप्ड हों, तो मजबूत युग्मन ठीक है।
dsimcha

5
मंत्र सरल है, "सिर्फ इसलिए कि आप प्ले-डोह को आकार दे सकते हैं जैसे कि कुछ भी करने का मतलब यह नहीं है कि आपको सब कुछ प्ले-डोह से बाहर करना चाहिए।" ;)
इवान प्लास

73

अनुभव।

जैसा कि आप कहते हैं कि वे विभिन्न नौकरियों के लिए उपकरण हैं, लेकिन वाक्यांश के बारे में आया क्योंकि लोग उस तरह से इसका उपयोग नहीं कर रहे थे।

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

तो वंशानुक्रम पर अनुकूल रचना क्यों - अच्छी तरह से सिर्फ इसलिए कि अधिक बार वर्गों के बीच संबंध एक बहुरूपिया नहीं है। यह बस लोगों को याद दिलाने में मदद करने के लिए मौजूद है कि विरासत में मिला कर घुटने का जवाब नहीं देना चाहिए।


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

13
@ मेसन: किसी भी मंत्र की तरह, "इनहेरिटेंस पर एहसान रचना" को शुरुआती प्रोग्रामर पर लक्षित किया जाता है। यदि आप पहले से ही जानते हैं कि वंशानुक्रम का उपयोग कब करना है और रचना का उपयोग कब करना है तो इस तरह मंत्र को दोहराना व्यर्थ है।
डीन हार्डिंग

7
@ डीन - मुझे यकीन नहीं है कि शुरुआत वही है जो विरासत की सर्वोत्तम प्रथाओं को नहीं समझता है। मुझे लगता है कि इसके अलावा भी बहुत कुछ है। गरीब विरासत मेरी नौकरी में कई, कई सिरदर्द का कारण है और यह प्रोग्रामर द्वारा लिखित कोड नहीं है जिन्हें "अंक" माना जाएगा।
निकोल

6
@ संदर्भ: पहली बात जब मैं सुनता हूं तो मुझे लगता है कि, "कुछ लोगों के पास दस साल का अनुभव है, और कुछ लोगों के पास एक वर्ष का अनुभव दस बार दोहराया गया है।"
मेसन व्हीलर

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

43

यह एक नया विचार नहीं है, मेरा मानना ​​है कि यह वास्तव में GoF डिज़ाइन पैटर्न बुक में पेश किया गया था, जो कि 1994 में प्रकाशित हुआ था।

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

GoF पुस्तक से:

वंशानुक्रम अपने माता-पिता के कार्यान्वयन के विवरण के लिए एक उपवर्ग को उजागर करता है, यह अक्सर कहा जाता है कि 'विरासत टूटता है'

GoF पुस्तक पर विकिपीडिया लेख का एक अच्छा परिचय है।


14
मैं इससे सहमत नहीं हूं। आपको उस वर्ग का कार्यान्वयन विवरण जानने की आवश्यकता नहीं है जिसे आप विरासत में प्राप्त कर रहे हैं; केवल सार्वजनिक और संरक्षित सदस्य वर्ग द्वारा उजागर किए गए। यदि आपको कार्यान्वयन के विवरण को जानना है, तो आप या जिसने भी लिखा है आधार वर्ग कुछ गलत कर रहा है, और यदि दोष आधार वर्ग में है, तो रचना आपको इसके चारों ओर तय / काम करने में मदद नहीं करेगी।
मेसन व्हीलर

18
आप किसी ऐसी चीज से असहमत हो सकते हैं जिसे आपने पढ़ा नहीं है? GoF से एक ठोस पृष्ठ और चर्चा का एक आधा हिस्सा है जो आपको केवल एक छोटा सा दृश्य मिल रहा है।
फिलोसोडैड

7
@ फोलोसोडैड: मैं किसी ऐसी चीज से असहमत नहीं हूं जिसे मैंने पढ़ा नहीं है। मैं इस बात से असहमत हूं कि डीन ने क्या लिखा है, "परिभाषा के अनुसार, आपको उस कक्षा का कार्यान्वयन विवरण जानना होगा, जिसे आप विरासत में प्राप्त कर रहे हैं," जो मैंने पढ़ा है।
मेसन व्हीलर

10
मैंने जो लिखा है, वह GoF पुस्तक में वर्णित एक सारांश है। हो सकता है कि मैंने इसे थोड़ा दृढ़ता से सुना हो (आपको सभी कार्यान्वयन विवरणों को जानने की आवश्यकता नहीं है ) लेकिन यही सामान्य कारण है कि GoF इनहेरिटेंस पर रचना का पक्ष लेने के लिए कहता है।
डीन हार्डिंग

2
अगर मैं गलत हूँ तो मुझे सुधारो लेकिन मैं इसे "स्पष्ट वर्ग संबंधों (यानी अंतर्विरोध) के पक्ष में (यानी विरासत) के रूप में देखता हूं।" पूर्व आपको बताएंगे कि आपको यह बताने की आवश्यकता नहीं है कि यह कैसे करना है। उत्तरार्द्ध न केवल आपको बताता है कि यह कैसे करना है बल्कि आपको सड़क पर नीचे पछतावा देगा।
इवान प्लाइस

26

आपके प्रश्न के कुछ अंशों का उत्तर देने के लिए, मेरा मानना ​​है कि यह अवधारणा पहली बार GOF डिज़ाइन पैटर्न: पुन: प्रयोज्य ऑब्जेक्ट-ओरिएंटेड सॉफ़्टवेयर बुक के तत्वों में प्रकट हुई , जो कि 1994 में पहली बार प्रकाशित हुई थी। वाक्यांश परिचय में पेज 20 के शीर्ष पर दिखाई देता है:

वंशानुक्रम पर अनुकूल वस्तु रचना

वे इस कथन को रचना के साथ विरासत की संक्षिप्त तुलना के साथ पेश करते हैं। वे कहते हैं कि "विरासत का कभी उपयोग न करें"।


23

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

यह सच क्यों है? क्योंकि वंशानुक्रम 2 वर्गों के बीच तंग, संकलन-समय युग्मन बनाता है। इसके विपरीत रचना ढीली युग्मन है, जो दूसरों के बीच स्पष्ट अलगाव को सक्षम बनाता है, रनटाइम पर निर्भरता बदलने की संभावना और आसान, अधिक पृथक निर्भरता परीक्षण।

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

उस कारण से (अन्य लोगों के बीच), आप शायद वेनिला विरासत की तुलना में इंटरफ़ेस कार्यान्वयन या अमूर्त वर्गों के रूप में अधिक बार इस्तेमाल होने वाले वंशानुक्रम को देखेंगे।

एक (रूपक) उदाहरण हो सकता है:

"मेरे पास एक सांप वर्ग है और मैं उस वर्ग के हिस्से के रूप में शामिल करना चाहता हूं जब साँप काटता है तो मुझे होता है। मुझे लगता है कि साँप को एक बिटारनिमल वर्ग विरासत में मिला है जिसमें काटने () विधि है और विषैले काटने को प्रतिबिंबित करने के लिए उस विधि को ओवरराइड करता है। । लेकिन इनहेरिटेंस से अधिक रचना मुझे चेतावनी देती है कि मुझे इसके बजाय रचना का उपयोग करने की कोशिश करनी चाहिए ... मेरे मामले में, यह सर्प में काटता हुआ सदस्य हो सकता है। कई उपवर्गों के साथ काटने वाला वर्ग अमूर्त (या एक इंटरफ़ेस) हो सकता है। मुझे अच्छी चीजें जैसे कि VenomousBite और DryBite उपवर्ग होते हैं और सांप की उम्र बढ़ने पर उसी सांप के काटने पर बदलने में सक्षम होता है। इसके अलावा अपनी अलग कक्षा में एक काटने के सभी प्रभावों को संभालने से मुझे उस फ्रॉस्ट क्लास में इसका पुन: उपयोग करने की अनुमति मिल सकती है। , क्योंकि ठंढ काटता है, लेकिन एक BiterAnimal नहीं है, और इतने पर ... "


4
सांप के साथ बहुत अच्छा उदाहरण है। मैं इसी तरह के एक मामले में हाल ही में अपनी कक्षाओं के साथ मिला
मक्सी

22

रचना के लिए कुछ संभावित तर्क:

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

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

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

तो, यह हो सकता है क्योंकि संरचना स्वाभाविक रूप से एक सरल रूपक है जिसमें विरासत की तुलना में कम सैद्धांतिक बाधाएं हैं। इसके अलावा, ये विशेष कारण डिज़ाइन समय के दौरान अधिक स्पष्ट हो सकते हैं, या संभवतः विरासत के कुछ दर्द बिंदुओं से निपटने के दौरान बाहर हो सकते हैं।

डिस्क्लेमर:
जाहिर तौर पर इसका स्पष्ट रास्ता नहीं है। प्रत्येक डिजाइन कई पैटर्न / उपकरण का मूल्यांकन करता है। इनहेरिटेंस का व्यापक रूप से उपयोग किया जाता है, इसके बहुत सारे लाभ हैं और कई बार रचना की तुलना में अधिक सुरुचिपूर्ण है। ये कुछ संभावित कारण हैं जिनका उपयोग रचना के अनुकूल होने पर किया जा सकता है।


1
"जाहिर है इसकी यह स्पष्ट कटौती / एक रास्ता सड़क नहीं है।" जब रचना विरासत से अधिक (या समान रूप से) लचीली नहीं होती है? मैं तर्क था कि यह बहुत ज्यादा है एक-तरफ़ा सड़क। संरचना के एक विशेष मामले के लिए वंशानुक्रम सिर्फ वाक्यगत चीनी है।
weberc2

किसी भाषा का उपयोग करते समय रचना अक्सर लचीली नहीं होती है जो स्पष्ट रूप से लागू किए गए इंटरफेस का उपयोग करके संरचना को लागू करती है, क्योंकि उन इंटरफेस को समय के साथ एक पिछड़े-संगत तरीके से विकसित करने की अनुमति नहीं है। #jmtcw
MikeSchinkel

11

शायद आपने पिछले कुछ महीनों में लोगों को यह कहते हुए देखा होगा, लेकिन यह बहुत से लंबे समय तक अच्छे प्रोग्रामर के लिए जाना जाता है। मैं निश्चित रूप से यह कह रहा हूं कि लगभग एक दशक के लिए उपयुक्त है।

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

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

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

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

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


3
सब ठीक है, मुझे लगता है कि सी ++ परिप्रेक्ष्य से समझ में आता है। यह कुछ ऐसा है जिसके बारे में मैंने कभी नहीं सोचा था, क्योंकि यह डेल्फी में एक मुद्दा नहीं है, जो कि मैं ज्यादातर समय का उपयोग करता हूं। (कोई एकाधिक वंशानुक्रम नहीं है, और यदि आपके पास बेस क्लास में एक विधि है और एक अन्य विधि में एक ही नाम से एक व्युत्पन्न वर्ग है जो आधार विधि को ओवरराइड नहीं करता है, तो कंपाइलर एक चेतावनी जारी करेगा, ताकि आप गलती से समाप्त न हों इस तरह की समस्या के साथ।)
मेसन व्हीलर 23

1
@ मेसन: ऑब्जेक्ट पास्कल (उर्फ डेल्फी) का एंडर का संस्करण C ++ और जावा से बेहतर है जब यह नाजुक आधार वर्ग की विरासत की समस्या की ओर आता है। C ++ और Java के विपरीत, विरासत में मिली आभासी विधि का अधिभार निहित नहीं है।
बिट-टिडलर

2
@ बिट-ट्विडलर, आप C ++ और जावा के बारे में जो कहते हैं, वह स्मॉलटाकल, पर्ल, पायथन, रूबी, जावास्क्रिप्ट, कॉमन लिस्प, ऑब्जेक्टिव-सी और हर दूसरी भाषा के बारे में कहा जा सकता है, जो मैंने सीखी है, जो ओईएम सपोर्ट प्रदान करती है। उस ने कहा, googling से पता चलता है कि C # ऑब्जेक्ट पास्कल की लीड है।
btilly

3
ऐसा इसलिए है क्योंकि एंडर्स हेजलसबर्ग ने बोरलैंड के ऑब्जेक्ट पास्कल (उर्फ डेल्फी) और सी # के स्वाद को डिजाइन किया था।
बिट-ट्विडलर

8

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

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

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

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


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

8

यहां मेरे दो सेंट हैं (पहले से ही उठाए गए सभी उत्कृष्ट बिंदुओं से परे):

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

जो कोई भी समय बिताने या सलाह देने में बिताता है वह जानता है कि ऐसा अक्सर होता है, खासकर नए डेवलपर्स के साथ जिनके पास अन्य प्रतिमानों में अनुभव है:

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

तब (अक्सर अतिविशिष्ट शिक्षण के परिणामस्वरूप), वे विरासत के लाभों के बारे में सीखते हैं, लेकिन इसे अक्सर पुन: उपयोग के लिए कैच-ऑल समाधान के रूप में पढ़ाया जाता है। वे इस धारणा के साथ समाप्त होते हैं कि किसी भी साझा व्यवहार को विरासत के माध्यम से साझा किया जाना चाहिए। ऐसा इसलिए है क्योंकि ध्यान अक्सर उप-योग के बजाय कार्यान्वयन वंशानुक्रम पर होता है।

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

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

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


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

8

एक टिप्पणी में, मेसन ने उल्लेख किया कि एक दिन हम इनहेरिटेंस के बारे में बोलेंगे जो हानिकारक माना जाता है

मुझे आशा है।

विरासत के साथ समस्या एक बार सरल और घातक है, यह इस विचार का सम्मान नहीं करता है कि एक अवधारणा में एक कार्यक्षमता होनी चाहिए।

अधिकांश OO- भाषाओं में, जब आपको आधार वर्ग से विरासत में मिला होता है:

  • अपने इंटरफ़ेस से विरासत में मिला
  • इसके कार्यान्वयन से विरासत में (डेटा और विधियाँ दोनों)

और यहीं मुसीबत बन जाते हैं।

यह वह जगह है नहीं केवल दृष्टिकोण है, हालांकि 00 भाषाओं ज्यादातर इसके साथ फंस रहे हैं। सौभाग्य से इंटरफेस / अमूर्त वर्ग उन में मौजूद हैं।

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

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

(1) अवधारणाएँ कार्यान्वयन के लिए एक समझदार डिफ़ॉल्ट प्रदान कर सकती हैं, लेकिन चूंकि उनके पास कोई डेटा नहीं है, इसलिए इस डिफ़ॉल्ट को केवल अवधारणा द्वारा प्रस्तावित अन्य विधियों की अवधि में या स्थिरांक के रूप में परिभाषित किया जा सकता है।


7

सरल उत्तर है: विरासत में रचना की तुलना में अधिक युग्मन है। दो विकल्पों को देखते हुए, अन्यथा समकक्ष गुणों में से, वह चुनें जो कम युग्मित हो।


2
लेकिन यह पूरी बात है। वे "अन्यथा समकक्ष नहीं हैं ।" वंशानुक्रम लिस्कॉव प्रतिस्थापन और बहुरूपता को सक्षम करता है, जो ओओपी का उपयोग करने के पूरे बिंदु हैं। रचना नहीं है
मेसन व्हीलर

4
बहुरूपता / एलएसपी ओओपी के "पूरे बिंदु" नहीं हैं, वे एक विशेषता हैं। इनकैप्सुलेशन, एब्स्ट्रक्शन आदि भी है। इनहेरिटेंस का तात्पर्य है "ए" रिलेशनशिप, एग्रिगेशन मॉडल "ए" रिलेशनशिप है।
स्टीव

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

3
@ मेसन: गाइडलाइन "उत्तराधिकार पर रचना के पक्ष में है।" किसी भी तरह से इसका मतलब यह नहीं है या यहां तक ​​कि विरासत से बचने के लिए उपयोग नहीं करते हैं। सभी यह कहते हैं कि जब अन्य सभी चीजें समान होती हैं, तो रचना चुनें। लेकिन अगर आपको विरासत की आवश्यकता है, तो इसका उपयोग करें!
जेफरी फॉस्ट

7

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

इसी तरह, इनहेरिटेंस ऐसी चीजें कर सकता है जो रचना नहीं कर सकती, लेकिन आपको इसका उपयोग तब करना चाहिए, जब आपको इसकी आवश्यकता हो, और जब आप न करें। इसलिए यदि आप कभी भी यह मानने के लिए लालच नहीं करते हैं कि जब आपको विरासत की आवश्यकता होती है, तब आपको "पसंद रचना" की सलाह की आवश्यकता नहीं होती है। लेकिन कई लोगों को करना है, और ऐसा लगता है कि सलाह की जरूरत है।

यह माना जाता है कि जब आपको वास्तव में विरासत की आवश्यकता होती है, तो यह स्पष्ट है, और आपको इसका उपयोग करना चाहिए।

इसके अलावा, स्टीवन लोव का जवाब। वास्तव में, वास्तव में ऐसा है।


1
मुझे आपकी सादृश्य पसंद है
बैरिलोयड

2

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

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

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

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


-1

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

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

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