मौजूदा कक्षाएं


51

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

मुझे जावा में लिखे गए बहुत बड़े और जटिल टूल पर बदलाव करना है। इस टूल में एक लिंक किए गए सदस्य पदानुक्रम के साथ कई अलग-अलग वर्ग वस्तुओं के साथ निर्मित डेटा संरचना है। वैसे भी ...

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

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

  1. सभी डेटा कक्षाओं में वास्तविक कार्यान्वयन करने का कोई मतलब नहीं है क्योंकि यह हर बार समान होता है लेकिन इंटरफेस (मुझे लगता है) के साथ यह आवश्यक होगा।
  2. मुझे नहीं पता कि मैं अपनी विरासत कक्षाओं में से एक को इंटरफ़ेस में कैसे बदल सकता हूं। मेरे यहां चर हैं और उन्हें बिल्कुल वहां होना है।

मुझे वास्तव में यह नहीं मिलता है, तो कृपया कोई मुझे बताएगा कि इसे कैसे संभाला जाए? क्योंकि यह हर बार समान है, लेकिन इस इंटरफेस (मुझे लगता है कि) के साथ आवश्यक होगा

+1

बाहर की जांच इस सूत्र http://stackoverflow.com/questions/3556652/how-do-java-interfaces-simulate-multiple-inheritance 15 feb. 112011-02-15 11:58:06

  0

तुमने कहा था 'मैं इन कई कई डेटा वर्ग है जो लगभग सभी XmlElement का विस्तार करना चाहिए और उनमें से कुछ टैग की गईं 'और' सभी डेटा वर्गों में वास्तविक कार्यान्वयन करने का कोई मतलब नहीं है क्योंकि यह हर बार एक जैसा है लेकिन इंटरफेस (मुझे लगता है) के साथ यह आवश्यक होगा। ' --- तो आपकी समस्या पहले स्थान पर खराब हो गई है: एक वर्ग एक प्रकार है; यदि कई डेटा वर्गों की आवश्यकता जरूरी है, तो प्रत्येक डेटा क्लास का अपना विशिष्ट व्यवहार होना चाहिए। दूसरे शब्दों में, प्रत्येक डेटा क्लास को बेस क्लास में सदस्य फ़ंक्शंस को ओवरराइड करना चाहिए। Contrapositive भी रखता है। 06 jan. 152015-01-06 17:22:44

55

आपको शायद COMP का पक्ष लेना चाहिए विरासत पर ओशन (और प्रतिनिधिमंडल):

public interface TaggedInterface { 
    void foo(); 
} 

public interface XMLElementInterface { 
    void bar(); 
} 

public class Tagged implements TaggedInterface { 
    // ... 
} 

public class XMLElement implements XMLElementInterface { 
    // ... 
} 

public class TaggedXmlElement implements TaggedInterface, XMLElementInterface { 
    private TaggedInterface tagged; 
    private XMLElementInterface xmlElement; 

    public TaggedXmlElement(TaggedInterface tagged, XMLElementInterface xmlElement) { 
     this.tagged = tagged; 
     this.xmlElement = xmlElement; 
    } 

    public void foo() { 
     this.tagged.foo(); 
    } 

    public void bar() { 
     this.xmlElement.bar(); 
    } 

    public static void main(String[] args) { 
     TaggedXmlElement t = new TaggedXmlElement(new Tagged(), new XMLElement()); 
     t.foo(); 
     t.bar(); 
    } 
} 
+3

क्या मैं एक मूर्ख सवाल पूछ सकता हूं? उपरोक्त 'टैग की गईं XML एलीमेंट' कक्षा का निर्माता कहां है? 05 dec. 122012-12-05 16:12:10

+3

अब यह है। ध्यान देने के लिए धन्यवाद। 05 dec. 122012-12-05 16:38:28


4

पहले यह कोई मतलब नहीं है सभी डेटा कक्षाओं में वास्तविक कार्यान्वयन डाल करने के लिए।

टैग के लिए एकत्रीकरण का उपयोग करने के बारे में कैसे?

  1. Tags करने के लिए अपने Tagged वर्ग का नाम बदलें।

  2. एक Tagged इंटरफ़ेस बनाएँ:

    इंटरफ़ेस टैग की गईं { टैग getTags(); }

  3. , चलो "टैग" होने के लिए प्रत्येक वर्ग की जरूरत है कि Tagged को लागू करने और यह एक tags क्षेत्र है, जो getTags से दिया जाता है डालते हैं।

दूसरा मैं नहीं दिख रहा है कि कैसे मैं एक अंतरफलक के लिए मेरी विरासत वर्गों में से एक को बदल सकता है।मेरे यहां चर हैं और उन्हें बिल्कुल वहां होना है।

यह सही है, इंटरफेस में आवृत्ति चर नहीं हो सकते हैं। टैग को संग्रहीत करने वाली डेटा संरचनाएं, आईएमओ टैग की जाने वाली कक्षाओं का हिस्सा नहीं होना चाहिए। एक अलग डेटा संरचना में टैग फैक्टर।


2

मैं इसे इस तरह हल कर दूंगा: Tagged और XMLElement कक्षा (शायद आपको सार्वजनिक इंटरफ़ेस में सभी विधियों की आवश्यकता नहीं है) के लिए इंटरफेस निकालें। फिर, दोनों इंटरफेस को लागू करने और लागू करने वर्ग एक Tagged (आपका वास्तविक ठोस Tagged वर्ग) और एक XMLElement (आपका वास्तविक ठोस XMLElement वर्ग) हैं:

public class MyClass implements Tagged, XMLElement { 

    private Tagged tagged; 
    private XMLElement xmlElement; 

    public MyClass(/*...*/) { 
     tagged = new TaggedImpl(); 
     xmlElement = new XMLElementImpl(); 
    } 

    @Override 
    public void someTaggedMethod() { 
     tagged.someTaggedMethod(); 
    } 
    } 

public class TaggedImpl implements Tagged { 
    @Override 
    public void someTaggedMethod() { 
     // so what has to be done 
    } 
    } 

public interface Tagged { 
    public void someTaggedMethod(); 
    } 

(और XMLElement के लिए वही)


1

एक संभावित तरीका;

1- आप सामान्य कार्यक्षमता के लिए बेस क्लास (एसएस) बना सकते हैं, अगर आपको इसे तुरंत चालू करने की आवश्यकता नहीं है तो इसे सार बनाएं।

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

3- इस स्तर पर ठोस वर्ग (ते) में के लिए सार आधार वर्ग का विस्तार करने और लागू विशिष्ट इंटरफेस के साथ-साथ


73

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

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

आपकी समस्या एक क्लासिक केस है जहां एकाधिक विरासत उचित होगा। कोड को दोबारा करने के लिए कोई सुझाव वास्तव में आपको बता रहा है कि प्रोबलेम के आसपास कैसे काम करना है कि जावा में एकाधिक विरासत नहीं है।

यह भी चर्चा कि "ओह, प्रतिनिधिमंडल बेहतर है, ला-डी-दाह" धर्म को डिजाइन के साथ भ्रमित कर रहा है। कोई सही रास्ता नहीं है। चीजें या तो अधिक उपयोगी या कम उपयोगी हैं और यह सब कुछ है।

आपके मामले में एकाधिक विरासत अधिक उपयोगी और अधिक सुरुचिपूर्ण समाधान होगा।

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

असल में, आपके लिए मेरा समाधान "एक्स टैग की गईं, एक्सएमलेमेंट" बढ़ाएगा और यह सब कुछ होगा।

... लेकिन जैसा कि आप ऊपर दिए गए समाधानों से देख सकते हैं, ज्यादातर लोग सोचते हैं कि ऐसा समाधान कॉम्प्लेक्स और कंसफिंग करने का तरीका होगा!

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

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

आप 100% सही हैं कि एकाधिक विरासत मदद करेगा, और नहीं, यदि आप सोचते हैं कि जावा के पास यह होना चाहिए तो आप अपने कोड में कुछ भी गलत कर रहे हैं।

+3

यह शीर्ष उत्तर होना चाहिए :) 13 jun. 132013-06-13 11:08:25

+3

आमीन! और खूनी सी # और .NET लोगों के लिए यह सच है। बर्ट्रेंड मेयर ने एक बार कहा था कि एकमात्र कारण .net और जावा में एकाधिक विरासत नहीं है, एक वर्ग लोडर लिखने में कठिनाई है जो कई आधार वर्गों का समर्थन करेगी। 29 sep. 132013-09-29 15:53:46

+1

@ केमलएडोगन: सी ++ में, क्या आप किसी भी पॉइंटर को सीधे शीर्ष-स्तरीय ऑब्जेक्ट प्रकार पर डाल सकते हैं और उसके बाद सीधे अपने वास्तविक प्रकार या किसी सुपरप्राइप पर डाउनकास्ट कर सकते हैं? ऐसी क्षमता, और तथ्य यह है कि अपवाद और डाउनकास्ट पहचान-संरक्षण हैं, जावा के डिजाइन के लिए मूलभूत है। 17 dec. 132013-12-17 22:59:05

  0

यह उत्तर पक्षपातपूर्ण है और इस विशेष मामले में भी गलत हो सकता है। 'आपकी समस्या एक क्लासिक मामला है जहां एकाधिक विरासत उचित होगा।' --- सबसे पहले आप वास्तव में निश्चित नहीं हैं कि विवरण की कुछ पंक्तियों के साथ समस्या क्या है। दूसरा, समस्या क्लासिक केस की तरह नहीं लगती है। नियम 2 (http://www.parashift.com/c++-faq/mi-disciplines.html) अच्छे कारणों से आता है। टैग की गईं और XMLElement एबीसी की तरह नहीं लगता है। प्रभावी रूप से, एक उचित सी ++ एकाधिक विरासत प्रतिमान में पहले स्थान पर कई इंटरफेस को लागू करने का विचार है। 06 jan. 152015-01-06 17:38:36

  0

इस उत्तर का समर्थन करने के लिए, स्वामित्व कोड आपकी ऑब्जेक्ट्स को एक विशिष्ट वर्ग के उदाहरण होने की उम्मीद कर सकता है। यदि स्वामित्व कोड के दो टुकड़े एक ही वस्तु को दो वर्गों की अपेक्षा करते हैं, न तो दूसरे का एक उदाहरण, केवल एक ही विकल्प कक्षाओं के लिए इंटरफेस को प्रतिस्थापित करने के बेहद बदसूरत हैक का उपयोग करना हो सकता है जबकि सभी विधियां संगत हैं। 08 jun. 162016-06-08 17:16:46


4

Andreas_D suggested के समान लेकिन आंतरिक कक्षाओं के उपयोग के साथ। इस तरह आप वास्तव में प्रत्येक वर्ग का विस्तार करते हैं और वांछित होने पर इसे अपने कोड में ओवरराइड कर सकते हैं।

interface IBird { 
    public void layEgg(); 
} 

interface IMammal { 
    public void giveMilk(); 
} 

class Bird implements IBird { 
    public void layEgg() { 
     System.out.println("Laying eggs..."); 
    } 
} 

class Mammal implements IMammal { 
    public void giveMilk() { 
     System.out.println("Giving milk..."); 
    } 
} 

class Platypus implements IMammal, IBird { 

    private class LayingEggAnimal extends Bird {} 
    private class GivingMilkAnimal extends Mammal {} 

    private LayingEggAnimal layingEggAnimal = new LayingEggAnimal(); 

    private GivingMilkAnimal givingMilkAnimal = new GivingMilkAnimal(); 

    @Override 
    public void layEgg() { 
     layingEggAnimal.layEgg(); 
    } 

    @Override 
    public void giveMilk() { 
     givingMilkAnimal.giveMilk(); 
    } 
} 

1

बस सोच रहा है कि कोई आंतरिक (सदस्य) कक्षाओं (एलआरएम 5.3.7) का उपयोग नहीं कर सकता है? ईजी।

// original classes: 
public class Tagged { 
    // ... 
} 

public class XMLElement { 
    // ... 
} 

public class TaggedXmlElement { 
    public/protected/private (static?) class InnerTagged extends Tagged { 
     // ... 
    } 

    public/protected/private (static?) class InnerXmlElement extends XMLElement { 
     // ... 
    } 

} 

इस तरह आप एक वर्ग TaggedXmlElement जो वास्तव में दो मूल वर्गों से और TaggedXmlElement भीतर आप सदस्य वर्गों की गैर-निजी सदस्यों की पहुंच है सभी तत्व शामिल हैं हैं: इस तरह (पहले उत्तर ऊपर के आधार पर) । बेशक कोई "सुपर" का उपयोग नहीं करेगा, लेकिन सदस्य वर्ग विधियों को कॉल करें। वैकल्पिक रूप से कोई कक्षाओं में से एक को बढ़ा सकता है और दूसरे को सदस्य वर्ग बना सकता है। कुछ प्रतिबंध हैं, लेकिन मुझे लगता है कि वे सभी के आसपास काम किया जा सकता है।


0

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

public MyExtendedClass extends ClassA, ClassB { 
    public duplicateMethodName() { 
     return ClassA.duplicateMethodName(); 
    } 
} 

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

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


0

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

class YourButton extends Button implements YourFunctionSet { 
    private Modifier modifier; 

    public YourButton(Context context) { 
     super(context); 
     modifier = new Modifier(this); 
    } 

    public YourButton(Context context, AttributeSet attrs) { 
     super(context, attrs); 
     modifier = new Modifier(this); 
    } 

    public YourButton(Context context, AttributeSet attrs, int defStyle) { 
     super(context, attrs, defStyle); 
     modifier = new Modifier(this); 
    } 

    @Override 
    public void generateRandomBackgroundColor() { 
     modifier.generateRandomBackgroundColor(); 
    } 
} 

class Modifier implements YourFunctionSet { 

    private View view; 

    public Modifier(View view) { 
     this.view = view; 
    } 

    @Override 
    public void generateRandomBackgroundColor() { 
     /** 
     * Your shared code 
     * 
     * ...... 
     * 
     * view.setBackgroundColor(randomColor); 
     */ 
    } 
} 


interface YourFunctionSet { 
    void generateRandomBackgroundColor(); 
} 

समस्या यहाँ है, अपनी कक्षाओं में एक ही सुपर वर्ग की जरूरत है। तुम भी विभिन्न वर्गों का उपयोग करने की कोशिश कर सकते हैं, लेकिन जाँच किस प्रकार से है, उदाहरण के

public class Modifier{ 
private View view; 
private AnotherClass anotherClass; 

public Modifier(Object object) { 
    if (object instanceof View) { 
     this.view = (View) object; 
    } else if (object instanceof AnotherClass) { 
     this.anotherClass = (AnotherClass) object; 
    } 
} 

public void generateRandomBackgroundColor(){ 
    if(view!=null){ 
     //...do 
    }else if(anotherClass!=null){ 
     //...do 
    } 
} 
} 

के लिए तो यहाँ मूल रूप से मेरी संशोधक वर्ग वर्ग जो सभी कार्यान्वयन समाहित है।

उम्मीद है कि यह किसी की मदद करेगा।