2010-02-10 16 views
23

संरचना और विरासत।क्या कोई संरचना ऐसी विरासत को पूरा नहीं कर सकती है?

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

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

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

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

व्यवहार में इन विचारों का परीक्षण, शुद्ध इंटरफ़ेस आधारित बहुरूपता और वस्तु रचना का एक संयोजन के लिए पारंपरिक विरासत को छोड़कर रखने के लक्ष्य को

, मैं सोच रहा हूँ,

क्या वस्तु रचना है और इंटरफेस है कि विरासत कर सकते हैं को पूरा नहीं कर सकते ?

संपादित

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

+2

व्यक्तिगत रूप से, मुझे मिश्रण पसंद है। :) –

+1

मेरे पास प्रभावी डुप्लिकेशन की जांच करने के लिए समय नहीं है, लेकिन यह विरासत बनाम रचना विषय पूर्व में एसओ पर बार-बार दौरा किया जाता है। http://stackoverflow.com/questions/216523/object-oriented-best-practices-inheritance-v-composition-v-interfaces या http://stackoverflow.com/questions/1598722/should-i-use- विरासत -या-रचना। 'कोई भी इस विषय पर हमेशा एक मोड़ डाल सकता है और इसे एक उपन्यास चीजों पर ले सकता है ...' फिर भी एक बात हमें सहमत करनी चाहिए कि इस प्रकार का प्रश्न निश्चित या यहां तक ​​कि आधिकारिक उत्तर नहीं देता है। शायद एक सीडब्ल्यू अधिक उपयुक्त प्रारूप हो सकता है ... – mjv

+0

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

उत्तर

21

विरासत के साथ महसूस किया जा सकता है तकनीकी रूप से सब कुछ प्रतिनिधिमंडल के साथ भी महसूस किया जा सकता है। तो जवाब "नहीं" होगा।

प्रतिनिधिमंडल में विरासत को बदलने

मान लीजिए कि हम विरासत के साथ लागू निम्नलिखित वर्गों करते हैं:

public class A { 
    String a = "A"; 
    void doSomething() { .... } 
    void getDisplayName() { return a } 
    void printName { System.out.println(this.getDisplayName() }; 
} 

public class B extends A { 
    String b = "B"; 
    void getDisplayName() { return a + " " + b; } 
    void doSomething() { super.doSomething() ; ... }  
} 

सामान अच्छी तरह से काम करता है, और बुला बी का एक उदाहरण पर printName में "A B" प्रिंट होगा कंसोल।

अब, हम फिर से लिखने अगर उस प्रतिनिधिमंडल के साथ, हम पाते हैं:

public class A { 
    String a = "A"; 
    void doSomething() { .... } 
    void getDisplayName() { return a } 
    void printName { System.out.println(this.getName() }; 
} 

public class B { 
    String b = "B"; 
    A delegate = new A(); 
    void getDisplayName() { return delegate.a + " " + b; } 
    void doSomething() { delegate.doSomething() ; ... } 
    void printName() { delegate.printName() ; ... } 
} 

हम बी में printName परिभाषित करने की जरूरत है और जब बी instantiated है भी प्रतिनिधि बनाने के लिए। doSomething पर कॉल एक ही तरीके से विरासत के साथ काम करेगा। लेकिन printName पर कॉल कंसोल में "A" प्रिंट करेगा। वास्तव में प्रतिनिधिमंडल के साथ, हमने ऑब्जेक्ट इंस्टेंस और बेस विधियों को ओवरराइड करने वाले तरीकों को कॉल करने में सक्षम होने के आधार पर "यह" की शक्तिशाली अवधारणा खो दी।

यह भाषा में हल किया जा सकता है शुद्ध प्रतिनिधिमंडल का समर्थन करता है। शुद्ध प्रतिनिधिमंडल के साथ, प्रतिनिधि में "यह" अभी भी बी के उदाहरण का संदर्भ देगा जिसका अर्थ है कि this.getName() कक्षा बी से विधि प्रेषण शुरू करेगा। हम विरासत के साथ ही प्राप्त करते हैं। यह prototype-based भाषा जैसे Self में उपयोग की जाने वाली तंत्र है जिसमें प्रतिनिधिमंडल में एक अंतर्निहित सुविधा है (आप here पढ़ सकते हैं कि स्वस्थ कैसे स्वयं में कार्य करता है)।

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

public class A implements AInterface { 
    String a = "A"; 
    AInterface owner; // replace "this" 
    A (AInterface o) { owner = o } 
    void doSomething() { .... } 
    void getDisplayName() { return a } 
    void printName { System.out.println(owner.getName() }; 
} 

public class B implements AInterface { 
    String b = "B"; 
    A delegate = new A(this); 
    void getDisplayName() { return delegate.a + " " + b; } 
    void doSomething() { delegate.doSomething() ; ... } 
    void printName() { delegate.printName() ; ... } 
} 

हम मूल रूप से फिर से लागू करने क्या निर्मित विरासत प्रदान करता है। क्या इस का कोई मतलब निकलता है? सच में नहीं। लेकिन यह दिखाता है कि विरासत हमेशा प्रतिनिधिमंडल में परिवर्तित हो सकती है।

चर्चा

विरासत तथ्य यह है कि एक आधार वर्ग एक विधि है कि एक उप वर्ग में ओवरराइड की गई है कॉल कर सकते हैं की विशेषता है। उदाहरण के लिए यह template pattern का सार है। प्रतिनिधिमंडल के साथ ऐसी चीजें आसानी से नहीं की जा सकती हैं। दूसरी ओर, यह वही है जो विरासत को उपयोग करने में कठोर बनाता है। यह समझने के लिए एक मानसिक मोड़ की आवश्यकता है कि पॉलीमोर्फिक प्रेषण कहाँ होता है और यदि विधियों को ओवरराइड किया जाता है तो इसका क्या प्रभाव होता है।

विरासत के बारे में कुछ ज्ञात नुकसान हैं और नाजुकता यह डिज़ाइन में पेश हो सकती है। विशेष रूप से अगर वर्ग पदानुक्रम विकसित होता है। विरासत का उपयोग होने पर hashCode और equals में equality के साथ कुछ समस्याएं भी हो सकती हैं। लेकिन दूसरी तरफ, यह अभी भी कुछ समस्याओं को हल करने का एक बहुत ही शानदार तरीका है।

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

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

कुछ साहित्य

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

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

कक्षाओं की मजबूत युग्मन और अनावश्यक वर्ग के सदस्यों के प्रसार की वजह से

विरासत द्वारा प्रेरित, सुझाव संरचना और प्रतिनिधिमंडल का उपयोग करने के बजाय है आम हो जाओ। साहित्य में इसी तरह के रिफैक्टरिंग की प्रस्तुति से किसी को यह विश्वास हो सकता है कि ऐसा परिवर्तन एक सीधा उपक्रम है। [...]

+0

इस प्रकाशित अंश से प्रकाशित अंश का हिस्सा है ? यदि ऐसा है, तो मुझे एक लिंक या डोई में दिलचस्पी होगी। –

+2

पहला पैराग्राफ मेरा है और मेरी राय है। फिर उस विषय से संबंधित कागजात के 3 संदर्भ हैं जिनके लिए मैंने सार को उद्धृत किया है। डूई उन लिंक में पाया जा सकता है जो सभी पोर्टल.एसीएम.ऑर्ग को इंगित करते हैं। क्षमा करें अगर वह स्पष्ट नहीं था। अगर आप उन्हें पीडीएफ के रूप में नहीं ढूंढ पा रहे हैं तो मुझे बताएं। – ewernli

+0

धन्यवाद, मैं स्पष्टीकरण की सराहना करता हूं। –

3

संरचना जीवन को पेंच नहीं कर सकते हैं के रूप में विरासत करता है, जब त्वरित बंदूक प्रोग्रामर विधियां जोड़कर मुद्दों को हल करने और विस्तार पदानुक्रम (बजाय प्राकृतिक पदानुक्रम के लिए एक विचार करना) करने की कोशिश

रचना नहीं कर सकते परिणामस्वरूप अजीब हीरे होते हैं, जिससे रखरखाव टीमों को उनके सिर खरोंचने वाले रात के तेल को जलाने का कारण बनता है

विरासत जीओएफ डिजाइन पैटर्न में चर्चा का सार था जो प्रोग्रामर द्वारा पहले स्थान पर संरचना का उपयोग नहीं किया गया होता।

+0

मुझे एक ट्रोल के रूप में चिह्नित करें, लेकिन मैंने उन सभी गलतियों को उनसे सीखने से पहले किया था – questzen

1

एक gui टूलकिट पर विचार करें।

एक संपादन नियंत्रण एक खिड़की है, इसे खिड़की के करीबी/सक्षम/पेंट कार्यों का उत्तराधिकारी होना चाहिए - इसमें खिड़की नहीं है।

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

+0

जीयूआई कक्षाओं पर चर्चा करते समय, मुझे लगता है कि कक्षा संरचना के साथ दृश्य संरचना को भ्रमित करना बहुत आसान है। कोई IWindow विंडो जैसी वस्तुओं के लिए हस्ताक्षर घोषित कर सकता है, और खिड़की वास्तव में खिड़कियां खींचने और घटनाओं को संभालने के लिए। फिर IEDitControl और EditControl बनाएं, जो IWindow को लागू करें। एडिटकंट्रोल बस विंडो ऑब्जेक्ट में अपनी आईविंडो जिम्मेदारियों को प्रतिनिधि करता है। सार्वजनिक रूप से, एडिटकंट्रोल किसी अन्य IWindow की तरह दिखता है, और एडिट कंट्रोल सजावट के साथ विंडो की तरह काम करता है। आखिरकार, RichTextControl IEDitControl लागू करता है, जो अपने स्वयं के संपादन नियंत्रण ऑब्जेक्ट को प्रस्तुत करता है। पैटर्न श्रृंखला योग्य है। –

+1

सच है, विरासत के अधिकांश उदाहरण (कर्मचारी वर्ग आदि) संरचना के रूप में बेहतर तरीके से किए जाते हैं। लेकिन गुई टूलकिट वास्तव में विरासत से लाभ प्राप्त करते हैं (आईएमएचओ) –

+2

सम्मानपूर्वक: मेरी कंपनी ने नेट में एक विशाल विरासत प्रणाली को बनाए रखा है; WinForms के साथ एमएसएफटी के उदाहरण से, मूल देवताओं ने यूआई कक्षाओं को लागू करने के लिए बहुत सारी विरासत का उपयोग किया। हमारे पास 18 अद्वितीय (हालांकि समान) कॉम्बो बॉक्स, 12 आधार रूप हैं, और सीआईएल पर 8 स्तर तक एक विरासत पदानुक्रम है। हमारा यूआई ढांचा इस तरह की भूलभुलैया है, इसलिए असंगत और नाजुक, वर्तमान देव टीम इसमें थोड़ी सी बदलाव से डरती है। लेकिन, अक्सर, यह सब कोड नई जरूरतों से कम हो जाता है ... संरचना का मतलब यह होगा कि हम अंतहीन * व्युत्पन्न * नए संयोजनों की बजाय सुविधाओं को चुन सकते हैं और चुन सकते हैं। –

1

मैं इसके बारे में गलत हो सकता हूं, लेकिन मैं इसे किसी भी तरह से कहने जा रहा हूं, और यदि किसी के पास कोई कारण है तो मैं गलत हूं, कृपया केवल एक टिप्पणी का जवाब दें और मुझे वोट न दें। एक ऐसी स्थिति है जहां मैं सोच सकता हूं कि विरासत रचना से बेहतर होगी।

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

Widget baseWidget = new Widget(); 
CustomWidget customWidget = new CustomWidget(); 
baseWidget.addChildWidget(customWidget); 

बहुत साफ है, और बच्चे विगेट्स जोड़ने के लिए लाइब्रेरी की परंपराओं के साथ कतार में रहता है। हालांकि, संरचना के साथ, यह कुछ इस तरह होना चाहिए था:

Widget baseWidget = new Widget(); 
CustomWidget customWidget = new CustomWidget(); 
customWidget.addAsChildToWidget(baseWidget); 

के रूप में साफ नहीं है, और यह भी पुस्तकालय की परंपराओं टूट जाता है

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

+2

आपने जोर दिया कि विजेट बाहरी, बंद स्रोत लाइब्रेरी में था। यदि Widget.addChildWidget() ने टाइप विजेट का तर्क लिया है, तो आईएमओ विरासत ही एकमात्र व्यवहार्य विकल्प है। लाइब्रेरी में माता-पिता बच्चों को ट्रैक करते हैं, लेकिन आपके रचनात्मक उदाहरण के लिए कस्टमविड्ज को उनके माता-पिता को ट्रैक करने की बजाय ट्रैक करने की आवश्यकता होती है। (यक!) यदि विजेट.addChildWidget() ने टाइप IWidget का तर्क लिया है, तो रचना अभी भी काम कर सकती है, क्योंकि कस्टमविड्ज IWidget को कार्यान्वित कर सकता है, जबकि निजी व्यवहार के कुछ व्यवहारों को परिभाषित करता है। बीटीडब्ल्यू, इंटरफेस संरचना की असली शक्ति आईओसी और डीआई के साथ आता है। –

-1

हां। यह रन टाइम टाइप पहचान (आरटीटीआई) है।

+0

यदि आपको आरटीटीआई की ज़रूरत है, तो स्पष्ट रूप से, आप डीआईपी का उल्लंघन कर रहे हैं। लेकिन मैं एक इंटरफ़ेस 'getType() 'या समान फ़ंक्शन घोषित करें, और इंटरफ़ेस को कार्यान्वित करें। अब आपके पास "टाइप" की अपनी परिभाषा है, जिसे आप अपनी पसंद की किसी भी चीज़ में ढाला कर सकते हैं ... और कक्षाओं को एक-दूसरे से संबंधित होने की आवश्यकता नहीं है। – cHao

संबंधित मुद्दे