2010-02-24 13 views
8

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

जबकि मैं अभी भी जेनरिक के आसपास पकड़ पाने की कोशिश कर रहा हूं, मेरा सवाल यह है - क्या यह सही डिजाइन दृष्टिकोण है? इंटरफेस आपके डिजाइन को अधिक लचीला/decoupled बनाते हैं। जबकि जेनेरिक, प्रकार की सुरक्षा लागू करें और आपको एक विशिष्ट प्रकार के वर्ग के आसपास पारित करने के लिए लागू करें। वास्तव में आपके कोड को डीकॉप्लिंग करने में मदद नहीं करता है। क्या ये सही है?

एक उदाहरण -

public MyWizard extends SignupWizard<SignupSection, SignupObject, SignupListener, SignupView>{ 
} 

बजाय डिजाइन और अधिक लचीला अगर यह था होगा ..

public interface Wizardable{ 
    public SignableSection getSection(); 
    public SignableObject getSignableObject(); 
... 
} 

public MyWizard implements Wizardable{ 
.... 
} 
+1

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

+0

ऐसा लगता है कि मैं सी ++ में जावा की अपेक्षा करता हूं। इंटरफेस के बजाय –

उत्तर

4

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

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

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

जैसा कि मैंने एक टिप्पणी में उल्लेख किया है, कोई उप-वर्ग उन प्रकार के पैरामीटर सेट करेगा और उपयोगकर्ता को कुछ भी बेनकाब नहीं करेगा। तो आपके पास class MegaSignupWizard extends SignupWizard<MegaSignupSection, MegaSignupObject, MegaSignupListener, MegaSignupView> जैसा कुछ हो सकता है और सबकुछ MegaSignupWizard के साथ पूरी तरह मान्य है, जिसमें बिना किसी आवश्यकता के कक्षाओं में विशेष तरीकों तक पहुंच है। अब यह अच्छा है :)

1

मैंने देखा है नए चौखटे के कई इंटरफेस के बजाय एनोटेशन का उपयोग करते हैं कि , लेकिन मैंने उन्हें इंटरफेस के बजाय जेनेरिक का उपयोग नहीं किया है (जो भी इसका मतलब है - कृपया और बताएं)।

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

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

+0

एनोटेशन ?! ऐसा ढांचा क्या होगा? –

+1

उदाहरण के लिए सर्वलेट 3.0 एपीआई में @ जीईटी एनोटेशन: http://today.java.net/article/2008/10/08/introduction-servlet-30 –

+0

@ मुरली: कभी जेपीए के बारे में सुना है? लगभग केवल एनोटेशन। – whiskeysierra

3

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

0

जेनिक्स को वास्तव में शक्तिशाली कहां देखने के लिए जंगल 2 पर एक नज़र डालें। असल में, कोई ऑब्जेक्ट एक कशेरुक या किनारे हो सकता है जो नेटवर्क एल्गोरिदम में कुछ वाकई दिलचस्प विचारों के लिए बनाता है। आप बस इंटरफेस के साथ ऐसा नहीं कर सका।

मुझे यकीन नहीं है कि आपका उपर्युक्त उपयोग अच्छा दिखता है। यदि आप किसी ऑब्जेक्ट से विस्तार कर रहे हैं या इंटरफेस को कार्यान्वित कर रहे हैं तो आप वास्तव में ऐसी वस्तुओं को पारित नहीं करना चाहते हैं। जेनरिक का उपयोग सार के साथ एक वर्ग को लागू करने के लिए किया जाता है, जैसे संग्रह, जो कि किसी भी चीज़ पर कार्य कर सकता है। क्या होता है यदि मैं SignupWizard<int, int, int, int> पास करता हूं जो पूरी तरह मान्य है?

उस विशेष विचार के लिए, शायद आप इंटरफेस का उपयोग करना चाहते हैं। एक इंटरफेस परिभाषित विज़ार्ड है, प्रत्येक ऑब्जेक्ट इसे कार्यान्वित कर रहा है और mywizard .addaction (int position, wizardaction action) में सक्षम है। वास्तव में यह निश्चित रूप से एक इंटरफेस समस्या है।

मैं दूसरों से सहमत हूं - जेनरिकों का उपयोग पुस्तकालयों द्वारा आवश्यक होने पर किया जाता है।

+0

यदि वर्टेक्स और एज में एक सुपर इंटरफ़ेस है तो ऑब्जेक्ट वर्टेक्स या एज हो सकता है। –

+0

लेकिन आपके पास किनारों पर टाइप किए गए पैरामीटर नहीं हो सकते हैं। आपको ऑब्जेक्ट का उपयोग करना होगा या एक प्रकार से चिपकना होगा। – whiskeysierra

+0

यह पूरी तरह से मान्य है। कोई सबक्लास उन प्रकार के पैरामीटर सेट करेगा और उपयोगकर्ता को कुछ भी बेनकाब नहीं करेगा। तो आपके पास मेगासिग्नअप विज़ार्ड कुछ ऐसा हो सकता है जो साइनअप विज़ार्ड <मेगासिग्नअपसेक्शन, मेगासिग्नअप ऑब्जेक्ट, मेगासिग्नअप लिस्टनर, मेगासिग्नअप व्यू> और सब कुछ पूरी तरह से मेगासिग्नअप विज़ार्ड के साथ मान्य है, जिसमें बिना किसी आवश्यकता के कक्षाओं में विशेष तरीकों तक पहुंच है। –

1

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

+0

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

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