2012-02-22 12 views
8

वर्ग Foo (जो स्पष्टता के लिए नहीं एक सामान्य वर्ग है) के लिए निम्नलिखित निर्माता पर विचार करें:एक सामान्य निर्माता के लिए उपयोग केस क्या है?

public <T> Foo(T obj) { } 

यह निर्माताओं के लिए मान्य सिंटैक्स है, बस सामान्य generic methods साथ की तरह।

लेकिन इस वाक्यविन्यास का उपयोग क्या है? आम तौर पर जेनेरिक तरीके उनके रिटर्न प्रकार के लिए प्रकार की सुरक्षा प्रदान करते हैं, और कंपाइलर द्वारा टाइप अनुमान से लाभ प्राप्त कर सकते हैं। उदाहरण के लिए:

Pair<String, Integer> stringInt = Pair.of("asfd", 1234); 

लेकिन एक निर्माता के लिए एक कॉल हमेशा अपने घोषित वर्ग का एक उदाहरण देता है, इसलिए इसकी प्रकार पैरामीटर वापसी प्रकार पर कोई प्रभाव नहीं। निर्माता ऊपर सिर्फ अपनी erasure साथ प्रतिस्थापित किया जा सकता है:

public Foo(Object obj) { } 

पाठ्यक्रम जेनरिक का न केवल वापसी प्रकार के लिए प्रकार सुरक्षा के बारे में कर रहे हैं। निर्माता सिर्फ तर्क (रों) के प्रकार विवश करने के लिए पारित किया जा रहा चाहते हो सकता है हालांकि, ऊपर के तर्क अभी भी एक घिरे प्रकार पैरामीटर के लिए लागू होता है:।

public <N extends Number> Foo(N number) { } 

public Foo(Number number) { } //same thing 

सीमा के साथ भी नेस्टेड प्रकार पैरामीटर वाइल्डकार्ड का उपयोग नियंत्रित किया जाता है:

public <N extends Number, L extends List<N>> Foo(L numList) { } 

public Foo(List<? extends Number> numList) { } //same thing 

तो सामान्य निर्माता होने के लिए वैध उपयोग केस क्या है?

उत्तर

6

यहां एक संभावित प्रोग्राम है, जो कार्यात्मक प्रोग्रामिंग से अनुकूलित है। मान लीजिए कि हमारे पास Stream प्रकार है जिसमें कुछ आंतरिक राज्य है, जो बार-बार नए तत्वों को उपज देता है जब तक यह null लौटाता है। बाहर कॉल करने परवाह नहीं है क्या स्ट्रीम प्रकार की आंतरिक स्थिति प्रकार है, तो आप प्राप्तकर्ता को पता है कि आंतरिक स्थिति प्रकार है बिना की तरह

class Stream<E> { 
    <S> Stream(S initialState, StepFunction<E, S> stepFun) { 
    ... 
    } 
} 

कुछ मिल सकता है।

+0

आह, बहुत रोचक! +1 –

+0

+1, यह एक अच्छा उदाहरण है, हालांकि यह थोड़ा सा धोखा देता है क्योंकि ओपी विशेष रूप से कहता है कि संलग्न प्रकार सामान्य नहीं है। (' 'सामान्य होगा।) –

+0

@ जॉन फ़ेमिनेला - मेरा मतलब केवल मेरा विशिष्ट उदाहरण' फू 'सामान्य नहीं था, केवल भ्रम से बचने के लिए। मेरा मतलब यह जवाब पर प्रतिबंध के रूप में नहीं था। –

2

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

public <L extends List<? extends Number> & RandomAccess> Foo(L raNumList) { } 

... 

Foo f1 = new Foo(new ArrayList<Integer>()); 
Foo f2 = new Foo(new LinkedList<Integer>()); //compiler error 
+1

या प्री-जेनेरिक कोड के साथ पिछड़े संगतता के लिए, जहां 'Foo' ने' ऑब्जेक्ट 'लिया, लेकिन अब आप कुछ और अधिक विशिष्ट चाहते हैं। '<टी ऑब्जेक्ट और तुलनात्मक विस्तार करता है <>> Foo (T obj)'।/वास्तव में यह विश्वास नहीं है कि इनमें से कोई भी आम है। –

5

एक बात मैं अपने सिर के ऊपर से दूर सोच सकते हैं आप यह सुनिश्चित कर सकते हैं कि कि सीमा में पूरा किया जाता है: केवल सामान्य वाक्य रचना आप ले Number के List रों भी लागू करता है कि RandomAccess एक निर्माता घोषित करने के लिए अनुमति देता है एक ही तरह से कई मानकों में।

public <T> Foo (List<T> listA, List<T> listB) { 
    listA.addAll(listB); 
} 

का उपयोग वाइल्डकार्ड यहाँ जल्दी से बहुत बुरा बन जाएगा और संभव है कि आप वैसे भी चाहते हो नहीं:

एक स्पष्ट रूप से बेवकूफ और काल्पनिक लेकिन वैध निर्माता कि प्रतियां एक लक्ष्य के लिए एक स्रोत से एक सूची है। यह इसे अस्वीकार करने के लिए एक पूरी तरह से मनमाना प्रतिबंध भी होगा। तो यह मुझे समझ में आता है कि भाषा की कल्पना इसे अनुमति देता है।

+2

या शरीर के भीतर 'टी' का उपयोग करें:' फू (सूची ts) {टी t0 = ts.get (0); ts.set (0, ts.get (1)); ts.set (1, टी 0); } '। ठीक है, एक दृढ़ उदाहरण नहीं है। –

1

आप निर्माता पैरामीटर के लिए कुछ बाधाओं को लागू कर सकते हैं। जैसे निम्नलिखित कोड को दो पैरामीटर की आवश्यकता होती है जो इंटरफेस इंटरफेस और इंटरफेसबी को कार्यान्वित करते हैं।

<T extends InterfaceA & InterfaceB > Foo(T t1, T t2) { 

} 
1

मुख्य उपयोग यह सुनिश्चित करना है कि एकाधिक मानकों के बीच प्रकार की बाधाएं पूरी की जाएंगी। , Integer[] और List<string>

public <T> AssemblyLine(T[] starting, List<T> components) { 
    T[] a = components.toArray(starting); 
    Arrays.sort(a); 
    this.conveyorBelt.add(a); 
} 

यहाँ <T> सुनिश्चित करता है कि T[] और List<T> एक ही प्रकार T रखें, और नहीं (माना): यहाँ एक उदाहरण है कि एक विधानसभा लाइन पर घटकों का एक समूह कहते हैं सही क्रम में है।

+0

+1 मैं जेनेरिक सरणी और उदाहरण को पास करने की आवश्यकता आदि के बारे में भूल गया - अच्छा एक (मुझे लगता है कि हालांकि एक टाइपो है - यह 'घटक .toArray' होना चाहिए) –

+0

धन्यवाद! मैंने इसे ठीक कर दिया। –

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