दिलचस्प पोस्ट
हिम तेंदुए पर .profile और .bash_profile के बीच का अंतर बाहरी डोमेन से सीएसएस @ फ़ॉन्ट-चेहरे निरपेक्ष यूआरएल: फ़ायरफ़ॉक्स फ़ायरफ़ॉक्स में नहीं लोड हो रहा है क्यों इस कोड में कोई भी रिटर्न शामिल नहीं है? सूचियों की सूची में परिवर्तन करना जैक्सब अनमरशल टाइमस्टैम्प MySQL क्वेरी परिणाम उनके मूल डेटा प्रकार के रूप में प्राप्त करें? Asp.net में डिफ़ॉल्ट पृष्ठ सेट करें मैं कैसे जांच करूं यदि कोई वर्ण एक स्वर है? कैसे एक हेक्स स्ट्रिंग के लिए एक int बदलने के लिए? सी # में उपयोग किए गए स्टेटमेंट का उपयोग करना "संदर्भ मुक्त व्याकरण" बनाने की युक्तियां अजगर में एक अच्छा __hash__ फ़ंक्शन कैसे कार्यान्वित करें आईफोन लैंडस्केप एफएक्यू और सॉल्यूशंस सी + + टेम्पलेट, लिंकिंग त्रुटि UIScrollView छूता है

दो सामान्य प्रकारों के साथ एक इंटरफ़ेस लागू करने वाला जावा क्लास कैसे बना सकता है?

मेरे पास एक सामान्य अंतरफलक है

public interface Consumer<E> { public void consume(E e); } 

मेरे पास एक ऐसा वर्ग है जो दो प्रकार की ऑब्जेक्ट्स का सेवन करता है, इसलिए मैं ऐसा कुछ करना चाहता हूं:

 public class TwoTypesConsumer implements Consumer<Tomato>, Consumer<Apple> { public void consume(Tomato t) { ..... } public void consume(Apple a) { ...... } } 

जाहिरा तौर पर मैं ऐसा नहीं कर सकता

मैं अपने आप को प्रेषण को लागू कर सकता हूं, उदा

 public class TwoTypesConsumer implements Consumer<Object> { public void consume(Object o) { if (o instanceof Tomato) { ..... } else if (o instanceof Apple) { ..... } else { throw new IllegalArgumentException(...) } } } 

लेकिन मैं संकलन-समय टाइप-चेकिंग और समाधान भेजना चाहता हूं जो जेनेरिक प्रदान करता है।

मैं सोच सकता हूँ कि सबसे अच्छा समाधान अलग इंटरफेस को परिभाषित करना है, उदा

 public interface AppleConsumer { public void consume(Apple a); } 

कार्यात्मक रूप से, यह समाधान ठीक है, मुझे लगता है। यह सिर्फ वर्बोस और बदसूरत है

कोई विचार?

Solutions Collecting From Web of "दो सामान्य प्रकारों के साथ एक इंटरफ़ेस लागू करने वाला जावा क्लास कैसे बना सकता है?"

Encapsulation पर विचार करें:

 public class TwoTypesConsumer { private TomatoConsumer tomatoConsumer = new TomatoConsumer(); private AppleConsumer appleConsumer = new AppleConsumer(); public void consume(Tomato t) { tomatoConsumer.consume(t); } public void consume(Apple a) { appleConsumer.consume(a); } public static class TomatoConsumer implements Consumer<Tomato> { public void consume(Tomato t) { ..... } } public static class AppleConsumer implements Consumer<Apple> { public void consume(Apple a) { ..... } } } 

यदि इन स्थैतिक आंतरिक वर्गों को आप परेशान करते हैं, तो आप अनाम वर्गों का उपयोग कर सकते हैं:

 public class TwoTypesConsumer { private Consumer<Tomato> tomatoConsumer = new Consumer<Tomato>() { public void consume(Tomato t) { } }; private Consumer<Apple> appleConsumer = new Consumer<Apple>() { public void consume(Apple a) { } }; public void consume(Tomato t) { tomatoConsumer.consume(t); } public void consume(Apple a) { appleConsumer.consume(a); } } 

प्रकार के विस्मरण के कारण आप एक ही इंटरफ़ेस को दो बार लागू नहीं कर सकते (विभिन्न प्रकार के पैरामीटर के साथ)।

स्टीव मैकलेओड के एक पर आधारित एक संभावित समाधान यहां दिया गया है:

 public class TwoTypesConsumer { public void consumeTomato(Tomato t) {...} public void consumeApple(Apple a) {...} public Consumer<Tomato> getTomatoConsumer() { return new Consumer<Tomato>() { public void consume(Tomato t) { consumeTomato(t); } } } public Consumer<Apple> getAppleConsumer() { return new Consumer<Apple>() { public void consume(Apple a) { consumeApple(t); } } } } 

प्रश्न की निहित आवश्यकता Consumer<Tomato> और Consumer<Apple> ऑब्जेक्ट्स जो शेयर स्टेट थे। Consumer<Tomato>, Consumer<Apple> ऑब्जेक्ट्स की आवश्यकता अन्य तरीकों से होती है जो इन पैरामीटर के रूप में अपेक्षा करते हैं। राज्य को साझा करने के लिए मुझे एक वर्ग की आवश्यकता है

स्टीव का विचार दो आंतरिक वर्गों का उपयोग करना था, प्रत्येक एक भिन्न सामान्य प्रकार का प्रयोग करना था

यह संस्करण उपभोक्ता इंटरफ़ेस को लागू करने वाले ऑब्जेक्ट्स के लिए गेटर्स जोड़ता है, जिसे बाद में उम्मीद की जाने वाली अन्य विधियों के लिए दिया जा सकता है।

कम से कम, आप निम्न की तरह कुछ करने से आपके प्रेषण के कार्यान्वयन में एक छोटा सा सुधार कर सकते हैं:

 public class TwoTypesConsumer implements Consumer<Fruit> { 

फलों को टमाटर और एपल के पूर्वजों के रूप में जाना जाता है

बस इस पर ठोकर खाई यह बस हुआ, कि मुझे एक ही समस्या थी, लेकिन मैंने इसे एक अलग तरीके से हल किया: मैंने इस तरह एक नया इंटरफेस बनाया

 public interface TwoTypesConsumer<A,B> extends Consumer<A>{ public void consume(B b); } 

दुर्भाग्यवश, इसे Consumer<B> और Consumer<B> रूप में नहीं माना जाता है Consumer<B> सभी तर्क के विरुद्ध तो आपको अपने क्लास के अंदर दूसरे उपभोक्ता के लिए एक छोटे एडाप्टर बनाना होगा

 public class ConsumeHandler implements TwoTypeConsumer<A,B>{ private final Consumer<B> consumerAdapter = new Consumer<B>(){ public void consume(B b){ ConsumeHandler.this.consume(B b); } }; public void consume(A a){ //... } public void conusme(B b){ //... } } 

अगर कोई Consumer<A> आवश्यक है, तो आप बस इसे पास कर सकते हैं, और अगर Consumer<B> की आवश्यकता होती है तो बस Consumer<A>

आप इसे सीधे एक वर्ग में नहीं कर सकते क्योंकि नीचे की श्रेणी की परिभाषा सामान्य प्रकारों के विलोपन और इंटरफ़ेस घोषणा डुप्लिकेट के कारण संकलित नहीं की जा सकती।

 class TwoTypesConsumer implements Consumer<Apple>, Consumer<Tomato> { // cannot compile ... } 

समान श्रेणी के संचालन को एक वर्ग में पैक करने के लिए कोई अन्य समाधान आपकी कक्षा को परिभाषित करने की आवश्यकता है:

 class TwoTypesConsumer { ... } 

जो व्यर्थ है, जैसा कि आप दोनों कार्यों की परिभाषा को दोहराएँ / डुप्लिकेट करने की आवश्यकता है और उन्हें इंटरफ़ेस से संदर्भित नहीं किया जाएगा। आईएमएचओ यह कर रहा है यह एक बुरे छोटे और कोड दोहराव है जो मैं बचने की कोशिश कर रहा हूं।

यह एक संकेतक भी हो सकता है कि एक वर्ग में 2 अलग-अलग वस्तुओं का उपभोग करने के लिए ज़्यादा ज़िम्मेदारी है (यदि वे युग्मित नहीं हैं)।

हालांकि, मैं क्या कर रहा हूं और आप क्या कर सकते हैं, निम्नलिखित उपभोक्ताओं को निम्नलिखित तरीके से बनाने के लिए स्पष्ट फैक्टरी ऑब्जेक्ट को जोड़ना है:

 interface ConsumerFactory { Consumer<Apple> createAppleConsumer(); Consumer<Tomato> createTomatoConsumer(); } 

यदि वास्तव में उन प्रकार वास्तव में युग्मित (संबंधित) हैं तो मैं इस तरह से एक कार्यान्वयन बनाने की सिफारिश करेगा:

 class TwoTypesConsumerFactory { // shared objects goes here private class TomatoConsumer implements Consumer<Tomato> { public void consume(Tomato tomato) { // you can access shared objects here } } private class AppleConsumer implements Consumer<Apple> { public void consume(Apple apple) { // you can access shared objects here } } // It is really important to return generic Consumer<Apple> here // instead of AppleConsumer. The classes should be rather private. public Consumer<Apple> createAppleConsumer() { return new AppleConsumer(); } // ...and the same here public Consumer<Tomato> createTomatoConsumer() { return new TomatoConsumer(); } } 

इसका फायदा यह है कि कारखाना वर्ग दोनों कार्यान्वयन को जानता है, एक साझा राज्य है (यदि आवश्यक हो) और यदि आवश्यक हो तो आप अधिक युग्मित उपभोक्ताओं को वापस कर सकते हैं। कोई दोहराव नहीं है जो विधि घोषणा का उपयोग करता है जो अंतरफलक से प्राप्त नहीं होता है।

कृपया ध्यान दें कि यदि प्रत्येक उपभोक्ता पूरी तरह से संबंधित नहीं हैं तो वे स्वतंत्र (अभी भी निजी) वर्ग हो सकते हैं

उस समाधान के नकारात्मक पक्ष एक उच्च श्रेणी की जटिलता है (भले ही यह एक जावा फ़ाइल हो सकती है) और उस विधि का उपयोग करने के लिए जिसकी बजाय आपको एक और कॉल की आवश्यकता है:

 twoTypesConsumer.consume(apple) twoTypesConsumer.consume(tomato) 

आपके पास:

 twoTypesConsumerFactory.createAppleConsumer().consume(apple); twoTypesConsumerFactory.createTomatoConsumer().consume(tomato); 

संक्षेप में आप 2 जेनेरिक उपभोक्ताओं को दो आंतरिक कक्षाओं का उपयोग करते हुए एक शीर्ष-स्तरीय वर्ग में परिभाषित कर सकते हैं लेकिन आपको कॉल करने के मामले में उचित कार्यान्वयन उपभोक्ता के लिए पहला संदर्भ प्राप्त करना होगा क्योंकि यह केवल एक उपभोक्ता वस्तु नहीं हो सकता है