2015-06-01 9 views
7

का उपयोग कब करें, मैं सोच रहा था, सिंटैक्टिक अंतर से अलग, जब कोई सामान्य पैरामीटर स्वीकार करने वाली विधि पर एक सामान्य इंटरफ़ेस का उपयोग करेगा?जावा जेनेरिक इंटरफेस बनाम जेनेरिक तरीके, और एक

public interface Flight<T>{ 
    void fly(T obj); 
} 

से अधिक
public interface Flight{ 
    void <T> fly(T obj); 
} 
+2

क्या आप एक insatnce को लागू 'flight' सक्षम होना चाहते हैं 'फ्लाई' विधि में केवल एक चयनित प्रकार का डेटा या किसी भी प्रकार का डेटा संभालने के लिए? – Pshemo

उत्तर

5

आप एक सामान्य विधि घोषित, तो आप हमेशा फोन करने वाले निर्णय लेते हैं, किस प्रकार का तर्क प्रकार पैरामीटर के लिए उपयोग करने के लिए करते हैं। विधि का कार्यान्वयन सभी संभावित प्रकार के तर्कों से निपटने में सक्षम होना चाहिए (और इसमें वास्तविक प्रकार के तर्कों के बारे में पूछने का कोई तरीका भी नहीं है)।

कहा कि, <T> void fly(T obj); की तरह एक विधि कहा गया है कि फोन करने वाले T के लिए किसी भी प्रकार का उपयोग कर सकते हैं, जबकि केवल एक चीज कार्यान्वयन पर भरोसा कर सकते कि T के लिए वास्तविक प्रकार Object को आबंटित किया जाएगा (जैसे <T extends Object> घोषित कर दिया गया था, तो) ।

तो इस विशिष्ट उदाहरण में, यह की घोषणा से अलग नहीं है, जो मनमानी वस्तुओं को भी अनुमति देता है।

इसके विपरीत, एक interface पर एक प्रकार पैरामीटर अनुबंध का हिस्सा है और निर्दिष्ट या प्रतिबंधित किया जा सकता एक कार्यान्वयनinterface के द्वारा:

public interface Flight<T>{ 
    void fly(T obj); 
} 

public class X implements Flight<String> { 
    public void fly(String obj) { 
    } 
} 
तरह कार्यान्वयन की अनुमति देता है

कार्यान्वयन पक्ष पर T के प्रकार को ठीक करना। या

public class NumberFlight<N extends Number> implements Flight<N> { 
    public void fly(N obj) { 
    } 
} 

अभी भी सामान्य किया जा रहा है लेकिन प्रकार सीमित।


एक interface के हस्ताक्षर भी महत्वपूर्ण है जब interface ही किसी अन्य विधि का हस्ताक्षर है, उदा का एक हिस्सा है

public void foo(Flight<? super String> f) { 
    f.fly("some string value"); 
} 

यहाँ, Flight कार्यान्वयन, जो आप foo के पास, एक String मूल्य लेने वाली है, इसलिए Flight<String> या Flight<CharSequence> या Flight<Object> पर्याप्त हैं, लेकिन नहीं Flight<Integer> करने में सक्षम होना चाहिए। ऐसे अनुबंध को घोषित करने के लिए interface पर टाइप पैरामीटर की आवश्यकता है, interface के तरीकों पर नहीं।

+0

इसलिए, जेनेरिक विधि पर सामान्य इंटरफ़ेस दृष्टिकोण का उपयोग करके अभी भी एक डिज़ाइन निर्णय में उबाल जाता है। यह समझ में आता है, समीकरण में जेनेरिक प्रकार जोड़ना वास्तव में कौन से तरीकों और इंटरफेस को नहीं बदलता है, हालांकि यह कुछ प्रतिबंधों जैसे प्रकार प्रतिबंध को जोड़ता है। 'नंबरफ्लाइट' 'फ्लाइट' और' 'के बीच अनुबंध को बदले बिना प्रकार को प्रतिबंधित भी कर सकता है। यह तो दिलचस्प है. मैं अब और अधिक प्रबुद्ध हूँ, बहुत बहुत धन्यवाद! – yev

0

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

उदाहरण के लिए, ArrayList<E> एक सामान्य प्रकार है क्योंकि इसके अधिकांश संचालन (जोड़ें, प्राप्त करें, हटाएं आदि) एक के निर्माण पर निर्दिष्ट प्रकार पर भरोसा करते हैं।

कक्षा में केवल कुछ विधियों को विभिन्न प्रकारों पर भरोसा करते समय एक सामान्य विधि का उपयोग किया जाना चाहिए।

आप Java Docs में जेनेरिक के बारे में अधिक पढ़ सकते हैं।

0

उदाहरण के लिए कक्षा java.util.ArrayList<E> लें। जब उस प्रकार के चर बनाते समय, आप T के लिए एक ठोस प्रकार निर्दिष्ट करने के लिए है:

ArrayList<String> list = new ArrayList<>(); 

ये ठोस प्रकार, उपयोग किया जाता है जब List इंटरफ़ेस से तरीकों, प्रकार T साथ कि काम बुला। add विधि को कॉल करके, आप सूची में केवल String ऑब्जेक्ट्स जोड़ सकते हैं। get का उपयोग कर सूची से तत्वों को पुनर्प्राप्त करने के लिए, आपको कंक्रीट प्रकार String के तत्व मिलेंगे।

सामान्य तरीकों के लिए, T टाइप केवल इस विधि के लिए निर्दिष्ट है। और यदि विधियां उस सामान्य प्रकार का मान देती हैं तो यह अधिक समझ में आती है। आप अक्सर इस तरह कोड को खोजने:

MyObject obj = SomeClass.staticGenericMethod(MyObject.class) 

या

MyObject obj = classInstance.genericMethod(MyObject.class); 

और तुम बड़े अक्षर से अपने इंटरफेस नाम शुरू कर देना चाहिए: Flight<T>

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