2010-08-10 22 views
6

में टाइप चेकर को टमिंग करना मैंने सोचा कि मैं जेनरिक को बहुत अच्छी तरह समझता हूं, लेकिन स्पष्ट रूप से मैंने नहीं किया।जावा जेनरिक

import java.util.ArrayList; 

class Job<J extends Job<J,R>, R extends Run<J,R>> {} 
class Run<J extends Job<J,R>, R extends Run<J,R>> {} 

class Job2 extends Job<Job2,Run2> {} 
class Run2 extends Run<Job2,Run2> {} 

class RunList<J extends Job<J,R>, R extends Run<J,R>> extends ArrayList<R> {} 

class Foo { 
    // #1 problem 
    public void test1(RunList<Job,Run> why) {} 
    // #2 this doesn't work either 
    public void test2(RunList<Job<Job,Run>,Run<Job,Run>> why) {} 
    // #3 this works 
    public void test3(RunList<Job2,Run2> why) {} 
} 

संकलक हुए कहा कि "नौकरी" अपनी तरह सीमा के भीतर नहीं है ऊपर test1 विधि की अनुमति नहीं है,:

यहाँ समस्या के परीक्षण का मामला है। मैं थोड़े प्रकार को समझता हूं --- Job कच्चे प्रकार के रूप में Job<Job,Run> का विस्तार नहीं करता है, इसलिए त्रुटि। इसके विपरीत, test3 काम करता है।

अब सवाल यह है कि, मैं यह काम कैसे कर सकता हूं? मैंने # 2 की कोशिश की है, लेकिन यह या तो काम नहीं करता है। मुझे लगता है कि समस्या वास्तव में # 1 --- Job<Job,Run> के साथ समान है सीमाओं के भीतर नहीं है क्योंकि इसके प्रकार तर्क Job एक कच्चा प्रकार है।

क्या कोई जानता है कि प्रकार के चेकर को कच्चे प्रकार के उपयोग के अलावा खुश कैसे किया जाए? या यह जावा टाइप सिस्टम में अभी उपलब्ध नहीं है?

+0

तुम क्या आप काम करना चाहते हैं पर कोई अतिरिक्त जानकारी प्रदान कर सकते हैं? ऐसा लगता है कि आपके पास समाधान है - आप कौन सी काम करना चाहते हैं, और क्यों? – mlschechter

+0

ध्यान दें कि # 3 अर्थात् अलग है, और यह कोई समाधान नहीं है --- यह एक कामकाज भी नहीं है। # 3 प्रभावी रूप से आपको ArrayList देता है, और इसलिए उदाहरण के लिए आप वहां सादे रन ऑब्जेक्ट नहीं जोड़ सकते हैं। मैं सादे जॉब्स और रन के साथ रनलिस्ट चाहता हूं, उदाहरण के लिए मैं इसमें सादा रन ऑब्जेक्ट डाल सकता हूं। # 2, अगर काम किया, तो कुछ समान प्राप्त होगा। –

उत्तर

1

शायद:

public <J extends Job<J, R>, R extends Run<J, R>> void test(RunList<J, R> why) {} 
+0

लेकिन फिर मैं नहीं कर सकता क्यों। बैड (नया नौकरी()); –

+0

बल्कि, क्यों .add (नया रन()); –

+0

रनलिस्ट के प्रकार आर के तत्व हैं। इस प्रकार रन के कुछ उप-वर्ग हैं। सूची में जोड़ने में सक्षम होने के लिए आपको RunList को चलाने के सटीक उप-वर्ग को जानने की आवश्यकता है (या उस का उप-वर्ग)। रन आर के समान सबसे अच्छा है, और बदतर आर अन्य परिप्रेक्ष्य से, मान लें कि test2 का यह हो सकता है: "why.add (नया रन());", यदि आप लिखते हैं: रनलिस्ट आरएल = नया RuRunList (); test2 (आर एल); रन 2 run2 = rl.get (0); आपको get() लाइन पर क्लास कास्ट अपवाद मिलेगा। – nairb774

0

आप तो ArrayList के प्रकार पैरामीटर बदलते हैं तो आपको नई रन जोड़ सकते हैं();

+0

क्या आपका मतलब जेनेरिक के बिना कच्चे प्रकार 'ऐरेलिस्ट' है? – whiskeysierra

+0

लेकिन यह रनलिस्ट को कच्चे प्रकार के रूप में उपयोग करने से भी बदतर है। –

+0

@ विली मुझे और अधिक विशिष्ट होना चाहिए था। वर्ग RunList <जम्मू नौकरी फैली हुई है, आर भागो फैली> का प्रयोग करें फैली ArrayList {} यह आपको भी भागो प्रकार आर के किसी भी वस्तुओं मुझे यकीन है कि यह प्रभावित करेगा कि क्या नहीं कर रहा हूँ और साथ ही वस्तुओं को जोड़ने के लिए अनुमति देता है रनलिस्ट वर्ग के अन्य भागों। –

-1

आप सही हैं, यकीन नहीं है कि मैं वहां क्या सोच रहा था! आपकी टिप्पणी ने मुझे इसके बारे में सोचने के लिए प्रेरित किया और मैंने इसका परीक्षण किया और समस्या के कारण प्रकार चर Job<J extends Job<J... की पुनरावर्ती परिभाषा के साथ कुछ करने के लिए है, लेकिन मैं पूरी तरह स्पष्ट क्यों नहीं हूं। एक समाधान, अपनी परिभाषाओं से जे और आर के 'उपयोग' को हटा दें।

लंबे समय तक जवाब:

import java.util.ArrayList; 

class Job<J extends Job, R extends Run> {} 
class Run<J extends Job, R extends Run> {} 

class Job2 extends Job<Job2,Run2> {} 
class Run2 extends Run<Job2,Run2> {} 

class RunList<J extends Job, R extends Run> extends ArrayList<R> {} 

class Foo { 
    // #1 works now 
    public void test1(RunList<Job,Run> why) {} 
    // #2 works now too 
    public void test2(RunList<Job<Job,Run>,Run<Job,Run>> why) {} 
    // #3 still works 
    public void test3(RunList<Job2,Run2> why) {} 
    // #4 generic method 
    public <J extends Job, R extends Run> void test4(RunList<J,R> why) {} 

    public static void main(String[] args) { 
     // Calling them even works... 
     new Foo().test1(new RunList<Job,Run>()); 
     new Foo().test2(new RunList<Job<Job,Run>,Run<Job,Run>>()); 

     // Calling the generic method works too 
     new Foo().test4(new RunList<Job,Run>()); 
     new Foo().test4(new RunList<Job<Job,Run>,Run<Job,Run>>()); 
     new Foo().test4(new RunList<Job2,Run2>()); 

     // ...sort of 

     // This doesn't work 
     //new Foo().test1(new RunList<Job<Job,Run>,Run<Job,Run>>()); 

     // This doesn't work 
     //new Foo().test1(new RunList<Job2,Run2>()); 

    } 
} 
+0

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

+0

Kohsuke, आप जेनेरिक का उपयोग करने की योजना कैसे बनाते हैं? क्या आपका लक्ष्य संकलित समय पर लागू करने का लक्ष्य है कि आप RunList में केवल रन के उप-वर्ग शामिल हैं जिन्हें किसी निश्चित नौकरी उप-वर्ग के साथ संगत माना जाता है? उदाहरण के लिए, रनलिस्ट मान्य है लेकिन रनलिस्ट <जॉब 2, MyCustomRun> ऐसा नहीं है क्योंकि जॉब 2 केवल रन 2 के साथ काम करने के लिए लिखा गया था? इसके अलावा, क्या नौकरी और रन इंटरफेस बनाने में कुछ गड़बड़ है? – jaxzin

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