2010-10-20 12 views
10

अधिकांश डिज़ाइन पैटन किताबें कहती हैं कि हमें "वर्ग विरासत पर ऑब्जेक्ट संरचना का पक्ष लेना चाहिए।"कक्षा उत्तराधिकारी पर ऑब्जेक्ट संरचना का नुकसान

लेकिन क्या कोई मुझे एक उदाहरण दे सकता है कि विरासत ऑब्जेक्ट संरचना से बेहतर है।

उत्तर

4

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

ऐसी भाषाओं में जो सबटाइपिंग के बिना उप-वर्गीकरण की अनुमति देते हैं (जैसे CZ language), नियम "विरासत पर ऑब्जेक्ट संरचना का पक्ष" नियम जावा या सी # जैसी भाषाओं में उतना महत्वपूर्ण नहीं है।

+0

>> यदि आप ऐसी भाषा में प्रोग्रामिंग कर रहे थे जो सबटाइपिंग के बिना उपclassing की अनुमति देता है, तो आप सबसे अधिक स्क्रिप्टिंग भाषा का मतलब है? – Howard

+2

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

+1

जावा हो सकता है कि कचरा भी है क्योंकि इंटेगर की संख्याओं के आधार पर संख्या और बाइटइनपुटस्ट्रीम इनपुटस्ट्रीम बढ़ाता है और प्रत्येक ऑब्जेक्ट ऑब्जेक्ट से लॉक, हैश और समानता विधियों को प्राप्त करता है। जाहिर है, अगर कुछ भी विरासत में बुरा है, तो जावा बहुत शुरुआत से गलत है। – Val

11

विरासत is-a संबंधों के लिए उपयुक्त है। यह has-a संबंधों के लिए एक गरीब फिट है।

के बाद से दोनों के बीच वर्गों/घटकों सबसे रिश्तों has-a बाल्टी में गिर जाते हैं (उदाहरण के लिए, एक Car वर्ग एक HashMap की संभावना नहीं है, लेकिन यह एक HashMap हो सकता है), यह तो इस प्रकार की संरचना अक्सर मॉडलिंग संबंधों के लिए एक बेहतर विचार है विरासत के बजाय कक्षाओं के बीच।

यह कहना नहीं है कि विरासत उपयोगी नहीं है या कुछ परिदृश्यों के लिए सही समाधान नहीं है।

7

मेरा सरल जवाब यह है कि आपको व्यवहार उद्देश्यों के लिए विरासत का उपयोग करना चाहिए। सबक्लास को विधि और ऑब्जेक्ट के व्यवहार को बदलने के तरीकों को ओवरराइड करना चाहिए।

यह आलेख (गोफ में से एक, एरिच गामा के साथ साक्षात्कार) स्पष्ट रूप से बताता है कि क्यों Favor object composition over class inheritance

0

बस एक होने के रूप में "है-एक" या एक "है-एक" संबंध

इस उदाहरण में मानव इसके बारे में लगता है कि "है-एक" पशु, और यह से अलग डेटा विरासत में हो सकता है पशु वर्ग। इसलिए विरासत का उपयोग किया जाता है:

abstract class Animal { 
    private String name; 
    public String getName(){ 
     return name; 
    } 
    abstract int getLegCount(); 
} 

class Dog extends Animal{ 
    public int getLegCount(){ 
     return 4; 
    } 
} 

class Human extends Animal{ 
    public int getLegCount(){ 
     return 2; 
    } 
} 

संरचना किसी अन्य वस्तु का मालिक होने पर समझ में आता है। एक कुत्ते वस्तु के मालिक के रूप में एक मानव वस्तु की तरह। तो निम्न उदाहरण में एक मानव वस्तु "है-एक" कुत्ता वस्तु

class Dog{ 
    private String name; 
} 
class Human{ 
    private Dog pet; 
} 

आशा व्यक्त की कि मदद की ...

0

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

interface Xable { 
doSomething(); 
} 

class Aable implements Xable { doSomething() { /* behave like A */ } } 
class Bable implements Xable { doSomething() { /* behave like B */ } } 

class Bar { 
Xable ability; 

public void setAbility(XAble a) { ability = a; } 

public void behave() { 
ability.doSomething(); 
} 

} 
/*now we can set our ability in runtime dynamicly */ 

/*somewhere in your code */ 

Bar bar = new Bar(); 
bar.setAbility(new Aable()); 
bar.behave(); /* behaves like A*/ 
bar.setAbility(new Bable()); 
bar.behave(); /* behaves like B*/ 

यदि आपने विरासत का उपयोग किया है, तो "बार" व्यवहार को विरासत में "स्थिर" व्यवहार प्राप्त होगा।

1

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

0

उपशीर्षक के लिए विरासत आवश्यक है। पर विचार करें:

void TakeBase(Base b) { /* ... */ } 

TakeBase(new Composed()); // ERROR 

इसलिए, यदि आप बहुरूपता चाहते हैं, आप की जरूरत है:

class Base { 
    void Foo() { /* ... */ } 
    void Bar() { /* ... */ } 
} 

class Composed { 
    void Foo() { mBase.Foo(); } 
    void Bar() { mBase.Foo(); } 
    private Base mBase; 
} 

हालांकि ComposedFoo के तरीकों यह एक समारोह है कि प्रकार Foo के एक मूल्य की उम्मीद है के लिए पारित नहीं किया जा सकता का समर्थन करता है विरासत (या इसके चचेरे भाई इंटरफ़ेस कार्यान्वयन)।

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