दिलचस्प पोस्ट
डीजेंगो टेम्प्लेट लूप डिफॉल्ट को नहीं कर सकता घटनाओं के लिए बाध्यकारी आदेश? मैं एक फाइल "माइम-टाइप (सामग्री-प्रकार?)" कैसे पा सकता हूं? PHP – एक स्ट्रिंग में एक यूआरएल को लिंक जोड़ें PHP foreach लूप में एकाधिक अनुक्रमणिका चर क्या एक संपत्ति को केवल सी # में स्थापित करने का एक तरीका है कैसे दो पैटर्न के बीच लाइनों का चयन करने के लिए? रिफ्लेक्शन के साथ राइट जेनेरिक मेथड चुनें C ++ में झंडे के रूप में एनोम का उपयोग कैसे करें? सरणी में सबसे लंबी स्ट्रिंग ढूंढना मेरे एंड्रॉइड एप्लिकेशन में वेबपेज से क्लिक ईवेंट प्राप्त करें MVC 3 फ़ाइल अपलोड और मॉडल बाध्यकारी जावास्क्रिप्ट में साहचर्य सरणी / हैशिंग कैसे करें दृश्य नियंत्रकों के बीच डेटा पास करना एंड्रॉइड के साथ WCF सेवा कैसे खपत करें

जावा एकाधिक वंशानुक्रम

जावा की बहु विरासत समस्याओं को हल करने के तरीके को पूरी तरह से समझने की कोशिश में, मेरे पास एक क्लासिक प्रश्न है जिसे मुझे स्पष्ट करना चाहिए

चलो कहना है कि मेरे पास क्लास Animal इसके पास उप कक्षा Bird और Horse और मुझे एक वर्ग Pegasus बनाने की जरूरत है जो Bird एंड Horse से फैली हुई है क्योंकि Pegasus एक पक्षी और एक घोड़ा है

मुझे लगता है कि यह क्लासिक हीरा समस्या है। इस से निपटने के लिए क्लासिक तरीके से मैं क्या समझ सकता हूं, Animal , Bird और Horse क्लास इंटरफेस बनाने और उनके Pegasus को लागू करना है।

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

Solutions Collecting From Web of "जावा एकाधिक वंशानुक्रम"

आप पशु कक्षाओं (जैविक अर्थ में कक्षा) के लिए इंटरफेस बना सकते हैं, जैसे कि घोड़ों के लिए public interface Avialae और पक्षियों के लिए public interface Avialae (मैं कोई जीवविज्ञानी नहीं हूं, इसलिए शर्तें गलत हो सकती हैं)।

तब आप अभी भी एक बना सकते हैं

 public class Bird implements Avialae { } 

तथा

 public class Horse implements Equidae {} 

और भी

 public class Pegasus implements Avialae, Equidae {} 

टिप्पणियों से जोड़ना:

डुप्लिकेट कोड को कम करने के लिए, आप एक अमूर्त वर्ग बना सकते हैं जिसमें उन जानवरों के सामान्य कोड शामिल हैं जिन्हें आप लागू करना चाहते हैं।

 public abstract class AbstractHorse implements Equidae {} public class Horse extends AbstractHorse {} public class Pegasus extends AbstractHorse implements Avialae {} 

अद्यतन करें

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

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

ऑब्जेक्ट्स को एक साथ संयोजन करने के दो मौलिक दृष्टिकोण हैं:

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

यह काम करने का तरीका यह है कि आपके पास एक पशु वस्तु है उस ऑब्जेक्ट के भीतर आप आगे की ऑब्जेक्ट्स जोड़ते हैं, जो आपको आवश्यक गुण और व्यवहार देते हैं।

उदाहरण के लिए:

  • पक्षी विस्तारित करता है जानवर IFlier लागू करता है IFlier
  • घोड़े का विस्तार करता है पशु IHerbivore, IQuadruped लागू करता है
  • कवि की उमंग जानवरों को लागू करता है IHerbivore, IQuadruped, IFlier

अब IFlier इस तरह दिखता है:

  interface IFlier { Flier getFlier(); } 

तो Bird इस तरह दिखता है:

  class Bird extends Animal implements IFlier { Flier flier = new Flier(); public Flier getFlier() { return flier; } } 

अब आपके पास इनहेरिटेंस के सभी फायदे हैं आप कोड का पुनः उपयोग कर सकते हैं आप IFliers का संग्रह कर सकते हैं, और बहुविधता आदि के अन्य सभी लाभों का उपयोग कर सकते हैं।

हालांकि आपके पास संरचना से सभी लचीलेपन भी हैं आप प्रत्येक प्रकार के Animal को पसंद करते हुए आप कई अलग-अलग इंटरफेस और कम्पोजिट बैकिंग क्लास के रूप में आवेदन कर सकते हैं – जितना ज्यादा नियंत्रण के रूप में आपको इसकी आवश्यकता है कि प्रत्येक बिट कैसे सेट अप किया जाता है

संरचना पैटर्न के लिए वैकल्पिक दृष्टिकोण वैकल्पिक दृष्टिकोण

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

मेरे पास एक बेवकूफ विचार है:

 public class Pegasus { private Horse horseFeatures; private Bird birdFeatures; public Pegasus(Horse horse, Bird bird) { this.horseFeatures = horse; this.birdFeatures = bird; } public void jump() { horseFeatures.jump(); } public void fly() { birdFeatures.fly(); } } 

क्या मैं बतख-टाइपिंग की अवधारणा का सुझाव दे सकता हूं?

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

इस तरह की अवधारणा का उपयोग स्ट्रैटेजी पैटर्न में किया जाता है दिए गए उदाहरण वास्तव में आपको दिखाता है कि कैसे एक बतख FlyBehaviour और QuackBehaviour विरासत में FlyBehaviour और QuackBehaviour भी बतख हो सकता है, जैसे कि RubberDuck , जो उड़ नहीं सकते वे बक्से को एक Bird क्लास का विस्तार भी कर सकते थे, लेकिन फिर वे कुछ लचीलापन छोड़ देते, क्योंकि हर Duck उड़ान भरने में सक्षम होगा, यहां तक ​​कि खराब RubberDuck Duck भी।

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

एक घोड़े को आधा दरवाजे के साथ एक स्थिर में रखने के लिए सुरक्षित है, क्योंकि एक घोड़ा आधा दरवाजा से अधिक नहीं मिल सकता है। इसलिए मैं एक घोड़े की आवास सेवा की स्थापना करता हूं जो किसी प्रकार के घोड़े को स्वीकार करता है और इसे एक आधे दरवाजे के साथ एक स्थिर में रखता है।

तो क्या घोड़े का घोड़ा भी उड़ सकता है?

मैं कई विरासतों के बारे में बहुत कुछ सोचता था, लेकिन अब जब मैं 15 साल से अधिक समय तक प्रोग्रामिंग कर रहा हूं, तो मुझे अब कई विरासत को लागू करने की कोई परवाह नहीं है।

अधिक बार नहीं, जब मैंने एक ऐसे डिज़ाइन से सामना करने की कोशिश की जो कई विरासत की ओर इशारा करता था, तो मैं बाद में रिहा करने के लिए आ गया, मुझे याद आया कि समस्या डोमेन

या

यदि यह एक बतख और बतख की तरह लग रहा है लेकिन यह बैटरी की जरूरत है, तो आपके पास संभवतः गलत अमूर्तता है

जावा 8 में, जो अब तक फरवरी 2014 के विकास चरण में है, आप एक तरह से सी + + हासिल करने के लिए डिफ़ॉल्ट विधियों का उपयोग कर सकते हैं – जैसे कि एकाधिक भाग्य आप इस ट्यूटोरियल को भी देख सकते हैं जो कुछ उदाहरण दिखाता है जो आधिकारिक दस्तावेजों से काम करना शुरू करना आसान हो।

जावा में एकाधिक विरासत समस्या नहीं है, क्योंकि इसमें एकाधिक उत्तराधिकार नहीं हैं। असली बहु विरासत समस्या (हीरा समस्या) को हल करने के लिए यह डिजाइन द्वारा है।

समस्या को कम करने के लिए अलग रणनीतियां हैं सबसे तुरंत प्राप्त करने वाला एक समग्र ऑब्जेक्ट है जिसका पावेल सुझाव देता है (अनिवार्य रूप से यह कैसे सी ++ हैंडल करता है) मुझे नहीं पता है कि सी 3 रैखिकरण (या समान) के माध्यम से बहु वारिस जावा के भविष्य के लिए कार्ड पर है, लेकिन मुझे इसमें संदेह है।

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

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

यदि आप अपने पेगासस क्लास के भीतर अपने घोड़े और पक्षी क्रियान्वयन के तरीकों और विशेषताओं का उपयोग करने में सक्षम होना चाहते हैं, तो आप पेगासस को एक पक्षी और घोड़े की संरचना के रूप में लागू कर सकते हैं:

 public class Animals { public interface Animal{ public int getNumberOfLegs(); public boolean canFly(); public boolean canBeRidden(); } public interface Bird extends Animal{ public void doSomeBirdThing(); } public interface Horse extends Animal{ public void doSomeHorseThing(); } public interface Pegasus extends Bird,Horse{ } public abstract class AnimalImpl implements Animal{ private final int numberOfLegs; public AnimalImpl(int numberOfLegs) { super(); this.numberOfLegs = numberOfLegs; } @Override public int getNumberOfLegs() { return numberOfLegs; } } public class BirdImpl extends AnimalImpl implements Bird{ public BirdImpl() { super(2); } @Override public boolean canFly() { return true; } @Override public boolean canBeRidden() { return false; } @Override public void doSomeBirdThing() { System.out.println("doing some bird thing..."); } } public class HorseImpl extends AnimalImpl implements Horse{ public HorseImpl() { super(4); } @Override public boolean canFly() { return false; } @Override public boolean canBeRidden() { return true; } @Override public void doSomeHorseThing() { System.out.println("doing some horse thing..."); } } public class PegasusImpl implements Pegasus{ private final Horse horse = new HorseImpl(); private final Bird bird = new BirdImpl(); @Override public void doSomeBirdThing() { bird.doSomeBirdThing(); } @Override public int getNumberOfLegs() { return horse.getNumberOfLegs(); } @Override public void doSomeHorseThing() { horse.doSomeHorseThing(); } @Override public boolean canFly() { return true; } @Override public boolean canBeRidden() { return true; } } } 

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

किसी इकाई घटक-प्रणाली के दृष्टिकोण के लिए कुछ छद्म कोड इस तरह दिखाई दे सकता है:

 public void createHorse(Entity entity){ entity.setComponent(NUMER_OF_LEGS, 4); entity.setComponent(CAN_FLY, false); entity.setComponent(CAN_BE_RIDDEN, true); entity.setComponent(SOME_HORSE_FUNCTIONALITY, new HorseFunction()); } public void createBird(Entity entity){ entity.setComponent(NUMER_OF_LEGS, 2); entity.setComponent(CAN_FLY, true); entity.setComponent(CAN_BE_RIDDEN, false); entity.setComponent(SOME_BIRD_FUNCTIONALITY, new BirdFunction()); } public void createPegasus(Entity entity){ createHorse(entity); createBird(entity); entity.setComponent(CAN_BE_RIDDEN, true); } 

आप एक इंटरफ़ेस पदानुक्रम बना सकते हैं और फिर चयनित इंटरफेस से अपनी कक्षाएं बढ़ा सकते हैं:

 public interface IAnimal { } public interface IBird implements IAnimal { } public interface IHorse implements IAnimal { } public interface IPegasus implements IBird,IHorse{ } 

और फिर एक विशेष इंटरफ़ेस को बढ़ाकर, आवश्यकतानुसार अपनी कक्षाओं को परिभाषित करें:

 public class Bird implements IBird { } public class Horse implements IHorse{ } public class Pegasus implements IPegasus { } 

एहम, आपका क्लास केवल 1 अन्य के लिए उपवर्ग हो सकता है, लेकिन फिर भी, आप जितने चाहें उतने इंटरफेस लागू कर सकते हैं, जैसा आप चाहते हैं

एक पेगासस वास्तव में एक घोड़ा है (यह एक घोड़े का विशेष मामला है), जो उड़ने में सक्षम है (जो कि इस विशेष घोड़े का "कौशल" है)। दूसरी ओर, आप कह सकते हैं, कवि की उमंग एक चिड़िया है, जो चल सकता है, और 4 लेग-यह सब निर्भर करता है, यह आपके लिए कोड लिखना कितना आसान है।

आपके मामले की तरह आप कह सकते हैं:

 abstract class Animal { private Integer hp = 0; public void eat() { hp++; } } interface AirCompatible { public void fly(); } class Bird extends Animal implements AirCompatible { @Override public void fly() { //Do something useful } } class Horse extends Animal { @Override public void eat() { hp+=2; } } class Pegasus extends Horse implements AirCompatible { //now every time when your Pegasus eats, will receive +2 hp @Override public void fly() { //Do something useful } } 

इंटरफेस एकाधिक विरासत अनुकरण नहीं करते जावा रचनाकारों ने एकाधिक विरासत को गलत मान लिया, इसलिए जावा में ऐसी कोई चीज नहीं है।

यदि आप दो वर्गों की कार्यक्षमता को एक में जोड़ना चाहते हैं – वस्तु संरचना का उपयोग करें अर्थात

 public class Main { private Component1 component1 = new Component1(); private Component2 component2 = new Component2(); } 

और अगर आप कुछ विधियों का पर्दाफाश करना चाहते हैं, तो उन्हें परिभाषित करें और उनको संबंधित नियंत्रक को कॉल दें।

यहां इंटरफेस सुलभ हो सकते हैं – यदि Component1 इंटरफ़ेस 1 Interface1 और Component2 को Interface2 लागू करता है, तो आप परिभाषित कर सकते हैं

 class Main implements Interface1, Interface2 

ताकि आप ऑब्जेक्ट्स का एक दूसरे पर उपयोग कर सकें, जहां संदर्भ से यह अनुमति देता है।

तो मेरी दृष्टि में, आप हीरे की समस्या में नहीं जा सकते।

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

मैंने कुछ साल पहले संरचना पर एक बहुत व्यापक लेख लिखा था …

https://codereview.stackexchange.com/questions/14542/multiple-inheritance-and-composition-with-java-and-c-updated

जटिलता को कम करने और भाषा को सरल बनाने के लिए, जावा में एकाधिक वंशानुक्रम समर्थित नहीं है।

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

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

 class A { void msg() { System.out.println("From A"); } } class B { void msg() { System.out.println("From B"); } } class C extends A,B { // suppose if this was possible public static void main(String[] args) { C obj = new C(); obj.msg(); // which msg() method would be invoked? } } 

जावा → इंटरफ़ेस में म्यूटिपोर्ट इनहेरिटन्स की समस्या को हल करने के लिए उपयोग किया जाता है

श्री केवीआर द्वारा जे 2 ईई (कोर जावा) नोट्स

दिन – 27

  1. इंटरफेस मूल रूप से उपयोगकर्ता परिभाषित डेटा प्रकार विकसित करने के लिए उपयोग किया जाता है।
  2. इंटरफेस के संबंध में हम कई वारिसों की अवधारणा को प्राप्त कर सकते हैं।
  3. इंटरफेस के साथ हम बहुरूपता की अवधारणा को प्राप्त कर सकते हैं, गतिशील बाध्यकारी हैं और इसलिए हम स्मृति अंतरिक्ष और निष्पादन समय के चलते एक जावा प्रोग्राम के प्रदर्शन में सुधार कर सकते हैं।

एक इंटरफ़ेस एक निर्माण होता है जिसमें विशुद्ध रूप से अपरिभाषित तरीकों का संग्रह होता है या इंटरफ़ेस विशुद्ध रूप से सार तत्वों का एक संग्रह होता है।

[…]

दिन – 28:

इंटरफ़ेस (एस) की कक्षाओं में सुविधाओं का पुन: उपयोग करने के लिए सिंटैक्स-1:

 [abstract] class <clsname> implements <intf 1>,<intf 2>.........<intf n> { variable declaration; method definition or declaration; }; 

उपरोक्त वाक्यविन्यास सीएलएसएम् में वर्ग के नाम का प्रतिनिधित्व करता है जो इंटरफेस की 'एन' संख्या से सुविधाओं का उत्तराधिकारी है। 'इम्प्लीमेंट्स' एक ऐसा कीवर्ड है जिसका इस्तेमाल इंटरएक्ट (एक्सपेंसेस) की सुविधाओं को व्युत्पन्न कक्षा में प्राप्त करने के लिए किया जाता है।

[…]

सिंटेक्स-2 इंटरफ़ेस की एक और इंटरफ़ेस में 'एन' संख्या को प्राप्त करना:

 interface <intf 0 name> extends <intf 1>,<intf 2>.........<intf n> { variable declaration cum initialization; method declaration; }; 

[…]

सिंटेक्स-3:

 [abstract] class <derived class name> extends <base class name> implements <intf 1>,<intf 2>.........<intf n> { variable declaration; method definition or declaration; }; 
  1. क्षमताओं को परिभाषित करने के लिए इंटरफेस को परिभाषित करें आप कई क्षमताओं के लिए कई इंटरफेस को परिभाषित कर सकते हैं। इन क्षमताओं को विशिष्ट पशु या बर्ड द्वारा लागू किया जा सकता है
  2. गैर-स्थिर और गैर-सार्वजनिक डेटा / विधियों को साझा करके वर्गों के बीच संबंध स्थापित करने के लिए उत्तराधिकार का उपयोग करें।
  3. गतिशील रूप से क्षमताओं को जोड़ने के लिए डेकोरेटर_पाटन का उपयोग करें यह आपको विरासत वर्गों और संयोजनों की संख्या को कम करने की अनुमति देगा।

बेहतर समझने के लिए नीचे दिए गए उदाहरण पर एक नज़र डालें

डेकोरेटर पैटर्न का उपयोग कब करना है?