विरासत और बहुरूपता - उपयोग की आसानी बनाम शुद्धता

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

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

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

0
ro fr bn

10 उत्तर

मुझे लगता है कि आपको अपने में संबंधों को लागू करने में सक्षम होने के लिए इंटरफ़ेस को कार्यान्वित करना चाहिए (यह सी # में कर रहा है):

public interface IDamageable
{
    void AddDamage(int i);
    int DamageCount {get;}
}

आप इसे अपनी वस्तुओं में लागू कर सकते हैं:

public class Person : IDamageable

public class House : IDamageable

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

0
जोड़ा

आम तौर पर जब हम 'ए' बनाम 'के बारे में बात करते हैं तो' हम 'विरासत बनाम संरचना के बारे में बात कर रहे हैं।

उम ... क्षति काउंटर सिर्फ आपके व्युत्पन्न वर्गों में से एक की विशेषता होगी और वास्तव में आपके प्रश्न के संबंध में 'एक व्यक्ति क्षति क्षति' के संदर्भ में चर्चा नहीं की जाएगी।

यह देखो:

http://www.artima.com/designtechniques/compoinh.html

जो आपको रास्ते में मदद कर सकता है।

@ डेरेक : शब्द से, मैंने माना कि वहां था बेस क्लेज था, जिस सवाल को मैं फिर से पढ़ता हूं, अब देख रहा हूं कि वह क्या प्राप्त कर रहा है।

0
जोड़ा

यह सवाल वास्तव में भ्रमित है: /

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

    

डेटा के सेट जिन्हें सभी को उसी तरह संसाधित किया जाना चाहिए

  

किस तरह? क्या फ़ंक्शन द्वारा संसाधित सेट हैं? एक और कक्षा? डेटा पर वर्चुअल फ़ंक्शन के माध्यम से?

    

विशेष रूप से, अलग-अलग वस्तुएं आदर्श रूप से वही कार्य करती हैं, जो बहुरूपता के साथ बहुत आसानी से हासिल की जाएगी

  

"एक ही अभिनय" और बहुरूपता का आदर्श बिल्कुल असंबंधित है। Polymorphism कैसे हासिल करना आसान बनाता है?

0
जोड़ा

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

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

यदि आप टेम्पलेट रूट (सी ++ या इसी तरह के मानते हुए) जाना चाहते हैं, तो आप इसे मिक्सिन के साथ कर सकते हैं, लेकिन खराब होने पर यह बदसूरत हो सकता है।

0
जोड़ा

@Kevin

आम तौर पर जब हम 'ए' बनाम 'के बारे में बात करते हैं, तो' हम विरासत बनाम संरचना के बारे में बात कर रहे हैं।

     

उम ... क्षति काउंटर सिर्फ आपके व्युत्पन्न वर्गों में से एक की विशेषता होगी और वास्तव में आपके प्रश्न के संबंध में 'एक व्यक्ति क्षति क्षति' के संदर्भ में चर्चा नहीं की जाएगी।

Having the damage counter as an attribute doesn't allow him to diverse objects with damage counters into a collection. For example, a person and a car might both have damage counters, but you can't have a vector or a vector or anything similar in most languages. If you have a common Object base class, then you can shove them in that way, but then you can't access the getDamage() method generically.

वह अपने प्रश्न का सार था, जैसा कि मैंने इसे पढ़ा था। "क्या मुझे कुछ ऑब्जेक्ट्स के इलाज के लिए is-a और is-a का उल्लंघन करना चाहिए, जैसे कि वे समान हैं, भले ही वे नहीं हैं?"

0
जोड़ा

@Andrew

"अभिनय" और बहुरूपता का आदर्श बिल्कुल असंबंधित है। पॉलिमॉर्फिज्म कैसे हासिल करना आसान बनाता है?

वे सभी, उदाहरण के लिए, एक समारोह आम है। आइए इसे addDamage() पर कॉल करें। यदि आप ऐसा कुछ करना चाहते हैं:

foreach (obj in mylist)
    obj.addDamage(1)

फिर आपको या तो एक गतिशील भाषा की आवश्यकता है, या आपको उन्हें एक सामान्य अभिभावक वर्ग (या इंटरफेस) से विस्तार करने की आवश्यकता है। उदा .:

class Person : DamageCounter {}
class Car : DamageCounter {}

foreach (DamageCounter d in mylist)
    d.addDamage(1)

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

0
जोड़ा

बहुरूपता विरासत की आवश्यकता नहीं है । पॉलीमोर्फिज्म वह होता है जब आप एकाधिक ऑब्जेक्ट्स एक ही संदेश हस्ताक्षर (विधि) को लागू करते हैं।

0
जोड़ा

मैं जॉन से सहमत हूं, लेकिन मानते हुए कि आपको अभी भी एक अलग क्षति काउंटर क्लास की आवश्यकता है, आप कर सकते हैं:

class IDamageable {
  virtual DamageCounter* damage_counter() = 0;
};
class DamageCounter {
  ...
};

प्रत्येक क्षतिग्रस्त वर्ग को तब अपना खुद का नुकसान_कॉर्टर() सदस्य कार्य प्रदान करने की आवश्यकता होती है। इसका नकारात्मक पक्ष यह है कि यह प्रत्येक क्षतिग्रस्त वर्ग के लिए एक vtable बनाता है। आप इसके बजाय उपयोग कर सकते हैं:

class Damageable {
 public:
  DamageCounter damage_counter() { return damage_counter_; }
 private:
  DamageCounter damage_counter_;
};

लेकिन कई माता-पिता कई विरासत वाले कूल नहीं होते हैं जब एकाधिक माता-पिता के सदस्य चर होते हैं।

0
जोड़ा

"इसे सही करने" के लिए लंबे समय तक लाभ होगा, अगर केवल इसलिए कि सिस्टम को बनाए रखने वाला कोई व्यक्ति इसे समझने में आसान लगेगा, तो इसे समझना आसान होगा।

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

0
जोड़ा

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

class Damage {
    virtual void addDamage(int d) = 0;
    virtual int getDamage() = 0;
};

class Person : public virtual Damage {
    void addDamage(int d) {
       //...
        damage += d * 2;
    }

    int getDamage() {
        return damage;
    }
};

class Car : public virtual Damage {
    void addDamage(int d) {
       //...
        damage += d;
    }

    int getDamage() {
        return damage;
    }
};

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

0
जोड़ा