2011-04-02 14 views
10

मुझे पता है कि सी ++ का उपयोग कैसे करें - टेम्पलेट्स - एक विशेषज्ञ नहीं, आपको दिमाग। जावा जेनरिक (और उस मामले के लिए स्कैला) के साथ, मेरे पास diffuculties है। शायद, क्योंकि मैं अपने सी ++ ज्ञान को जावा दुनिया में अनुवाद करने का प्रयास करता हूं। मैंने कहीं और पढ़ा है, "वे एक जैसे नहीं हैं: जावा जेनरिक केवल सिंटैक्टिक चीनी बचत कास्ट हैं, सी ++ टेम्पलेट्स केवल एक गौरवशाली प्रीप्रोसेसर हैं" :-)जावा जेनरिक, समर्थन "विशेषज्ञता"? सी ++ टेम्पलेट्स के लिए अवधारणात्मक समानताएं?

मुझे पूरा यकीन है कि दोनों थोड़ा सा सरल है। तो, बड़े और सूक्ष्म अंतर को समझने के लिए, मैं विशेषज्ञता साथ प्रारंभ करने का प्रयास:

में सी ++ मैं डिज़ाइन कर सकते हैं एक खाका (समारोह की कक्षा) कि पर किसी भी प्रकार T कि समर्थन में कार्य करता है मेरी आवश्यक कार्रवाई:

template<typename T> 
T plus(T a, T b) { return a.add(b); } 

यह अब संभवतः किसी भी प्रकार के plus() आपरेशन कहते हैं कि यह कर सकते हैं add() [Note1] [1]

। 0

इस प्रकार, यदि Tadd(T) मेरा टेम्पलेट वोल काम का समर्थन करता है। यदि ऐसा नहीं होता है, संकलक तब तक शिकायत नहीं करेगा जब तक कि मैं plus() का उपयोग नहीं करता। अजगर में हम इस "बतख टाइपिंग" फोन:। * यह एक बतख की तरह कार्य करता है, एक बतख की तरह नीम हकीमों, यह एक बतख है * (बेशक, type_traits का उपयोग कर के साथ इस संशोधित किया गया है एक सा, लेकिन जब तक हमारे पास कोई अवधारणा नहीं है, तो यह है कि सी ++ टेम्पलेट्स कैसे काम करते हैं, है ना?)

मुझे लगता है कि जावा में जेनिक्स भी काम करता है, है ना? सामान्य प्रकार I डिवाइस का उपयोग "टेम्पलेट" के रूप में किया जाता है, जिसे मैं वहां रखने की कोशिश करता हूं, ठीक है? जहां तक ​​मैं समझता हूं कि मैं कुछ तर्कों पर बाधा डाल सकता हूं: यदि मैं अपने टेम्पलेट में add का उपयोग करना चाहता हूं, तो मुझे implement Addable पर तर्क तर्क घोषित करना होगा। सही बात? तो, कोई "बतख टाइपिंग" (बेहतर या बदतर के लिए)।

अब, में सी ++ मैं लिए चुन सकते हैं एक प्रकार पर विशेषज्ञ है कि कोई add():

template<> 
T plus<MyX>(MyX a, MyX b) { return a + b; } 

और अगर अन्य सभी प्रकार अभी भी "डिफ़ॉल्ट" कार्यान्वयन का उपयोग कर सकते हैं, अब मैंने MyX के लिए एक विशेष जोड़ा - बिना रनटाइम ओवरहेड के।

क्या कोई जावा जेनरिक तंत्र का एक ही उद्देश्य है? बेशक, प्रोग्रामिंग में सब कुछ करने योग्य है, लेकिन मेरा मतलब है अवधारणा, बिना किसी चाल और जादू के?

उत्तर

8

नहीं, जावा में जेनेरिक इस तरह से काम नहीं करते हैं।

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

तो, प्रत्येक प्रकार के चर के लिए आप केवल अपनी सीमाओं में परिभाषित विधियों को कॉल कर सकते हैं (कोई बतख टाइपिंग नहीं)।

इसके अलावा, कोई कोड जनरेशन नहीं है (कुछ एडाप्टर विधियों के अलावा जेनेरिक प्रकारों को लागू करने के उद्देश्य के लिए अन्य पैरामीटर प्रकारों के साथ विधियों को प्रतिनिधि करने के लिए)।मान लें तो आप इस

/** 
* interface for objects who allow adding some other objects 
*/ 
interface Addable<T> { 
    /** returns the sum of this object and another object. */ 
    T plus(T summand); 
} 

की तरह कुछ था तो हम दो तर्क के साथ हमारे sum विधि बना सकते हैं: (एनोटेशन में अतिरिक्त प्रकार की जानकारी के साथ)

public static <T extends Addable<T>> T sum(T first, T second) { 
    return first.plus(second); 
} 

स्थिर विधि इस तरह एक ही बाईटकोड को संकलित किया गया है :

public static Addable sum(Addable first, Addable second) { 
    return first.plus(second); 
} 

यह प्रकार विलोपन कहा जाता है।

अब इस विधि एक addable प्रकार के दो तत्वों की प्रत्येक जोड़ी के लिए कहा जा सकता है, जैसे इस एक:

:

public class Integer implements Addable<Integer> { 
    public Integer plus(Integer that) { 
     return new Integer(this.value + that.value); 
    } 

    // private implementation details omitted 
} 

यहां होता है कि संकलक इस तरह एक अतिरिक्त कृत्रिम विधि बनाता है

public Object plus(Object that) { 
    return this.plus((Integer)that); 
} 

यह विधि केवल सामान्य प्रकार के जेनेरिक कोड द्वारा कॉल की जाएगी, यह संकलक की गारंटी देता है, यह मानते हुए कि आप कुछ असुरक्षित जगह नहीं कर रहे हैं - तो (Integer) यहां डाली गई गलती को पकड़ लेगा (और क्लासकास्ट अपवाद फेंक देगा)।

sum विधि अब हमेशा कॉल पहली वस्तु की plus विधि, वहाँ इस के आसपास कोई रास्ता नहीं है। प्रत्येक प्रकार के तर्क के लिए कोड उत्पन्न नहीं होता है (यह जावा जेनरिक और सी ++ टेम्पलेट्स के बीच महत्वपूर्ण अंतर है), इसलिए हम किसी विशेष विधि के साथ जेनरेट की गई विधि को प्रतिस्थापित नहीं कर सकते हैं।

बेशक, आप एक दूसरे sum विधि irreputable प्रस्तावित (अधिक भार के साथ) की तरह बना सकते हैं, लेकिन यह केवल यदि आप स्रोत कोड में सीधे MyX प्रकार का उपयोग करें, आप से sum विधि नहीं बुला रहे हैं जब चयन किया जाएगा कुछ अन्य सामान्य कोड जो होता है, MYX साथ parametrized जा करने के लिए इस तरह:

public static <T extends Addable<T>> product (int times, T factor) { 
    T result = factor; 
    while(n > 1) { 
     result = sum(result, factor); 
    } 
    return result; 
} 

अब product(5, new MyX(...)) हमारे sum(T,T) विधि (जो बारी में plus विधि कॉल), नहीं किसी भी अतिभारित sum(MyX, MyX) विधि कॉल करेंगे।

(JDK 7 जो रन टाइम पर हर तर्क से विशेषज्ञता की अनुमति देता है एक नया dynamic विधि प्रेषण मोड लेता है, लेकिन यह जावा भाषा, केवल अन्य JVM-आधारित भाषाओं द्वारा इस्तेमाल किया जा करने का इरादा द्वारा नहीं किया जाता।)

+2

प्रकार मिटाई गई विधि 'जोड़ योग्य राशि (पहले जोड़ा जा सकता है, जोड़ने योग्य दूसरा) ' – irreputable

+0

@irreputable: धन्यवाद, आप सही हैं। मैंने इसे बदल दिया –

+0

'योग' के लिए जेनेरिक काम कैसे करता है, इसकी महान व्याख्या। अब मैं इसे अपने पुराने जावा ज्ञान में अनुवाद कर सकता हूं। लेकिन यहां क्या exaclty * मिटा दिया गया है *? "टाइप एरर" नाम का क्या अर्थ है? – towi

2

HI,

जावा जेनरिक यह सी ++ टेम्पलेट से अलग है।

उदाहरण:

जावा कोड:

public <T> T sum(T a, T b) { 
    T newValue = a.sum(b); 
    return newValue; 
} 

जावा में इस कोड क्योंकि जेनरिक आधार वर्ग java.lang.Object है काम नहीं करते है, तो आप इस वर्ग के केवल विधि का उपयोग कर सकते हैं।

public <T extends Number> T sum(T a, T b) { 
    T newValue = a.sum(b); 
    return newValue; 
} 
इस मामले जेनरिक के आधार वर्ग java.lang.Number है ताकि आप पूर्णांक, डबल, लांग ecc उपयोग कर सकते हैं में

..

विधि:

आप इस निर्माण कर सकते हैं इस तरह methis "योग" java.lang.Number के कार्यान्वयन पर निर्भर करता है।

अलविदा

3

नहीं है - लेकिन अपने विशेष समस्या एक से अधिक भार मुद्दे के अधिक है।

कोई समस्या नहीं 2 plus तरीकों इन

<T extends Addable> 
T plus(T a, T b) { .. } 

MyX plus(MyX a, MyX b) { .. } 

यह भी काम करता है की तरह परिभाषित करने के लिए करता है, तो MyX एक Addable है नहीं है; जावैक जानता है कि दूसरा से अधिक विशिष्ट है, इसलिए जब आप plus पर दो MyX तर्कों के साथ कॉल करते हैं, तो दूसरा plus चुना जाता है। एक मायने में जावा की अनुमति देने के तरीकों में से "विशेष" संस्करण है:

f(T1, T2, .. Tn) 

f(S1, S2, .. Sn) 

अच्छा काम करता है, तो प्रत्येक SiTi

सामान्य वर्गों के लिए की एक उप-प्रकार, हम क्या कर सकते हैं

class C<T extends Number> { ... } 

class C_Integer extends C<Integer>{ ... } 

कॉलर चाहिए "विशेष" संस्करण चुनने के लिए C<Integer> के बजाय C_Integer का उपयोग करें।


बतख टाइपिंग पर: जावा स्थिर टाइपिंग में और अधिक सख्त है - जब तक यह एक बतख है, यह एक बतख नहीं है।

+0

यह केवल ओवरलोडिंग है, यह काम नहीं करता है अगर 'प्लस' विधि को 'टी' का उपयोग करके कुछ सामान्य विधि से कहा जाता है और 'माईएक्स' कहा जाता है। –

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