2015-06-16 7 views
7

साथ एक पैरामिट्रीकृत प्रकार बदलने के लिए कैसे निम्नलिखित सेटअप पर विचार करें:अधिक विशिष्ट

public interface SuperType<V> { 
} 

SuperType विधि श्रृंखलन का समर्थन करता है:

हम एक अंतरफलक SuperType जो इस तरह parameterized है।

public interface SuperType<V, S extends SuperType<V, S>> { 

    public S doSomething(); 
} 

के SuperType<V, S extends SuperType<V, S>> के एक कार्यान्वयन पर विचार करें:

public class SubType<V> implements SuperType<V, SubType<V>> { 

    private final V value; 

    public SubType(V value) { this.value = value; } 

    public SubType<V> doSomething() { return this; } 
} 

किसी को दर्शाता है SubType<V> उदाहरण स्ट्रिंग्स के लिए उपयोग कर रहा है, लेकिन Object प्रदान करता है इसलिए यह एक और प्रकार पैरामीटर जो ठोस लागू करने उप प्रकार इस तरह प्रत्येक विधि द्वारा वापस कब्जा को परिभाषित करता है टाइप पैरामीटर V:

Object s = "Java Generics"; 
SubType<Object> x = new SubType<>(s); 

अब हम जो V के अधिक विशिष्ट प्रकार पैरामीटर लेता है और एक ही कार्यान्वयन प्रकार S लेकिन अब W extends V साथ पैरामिट्रीकृत रिटर्न SuperType<V, S extends SuperType<V, S>> के लिए एक और तरीका निर्धारित करना चाहते हैं:

public interface SuperType<V, S extends SuperType<V, S>> { 

    public S doSomething(); 

    public <W extends V, T extends SuperType<W, T>> T doMoreSpecific(Class<W> typeToken); 
} 

इस नए इंटरफ़ेस परिभाषा का समर्थन करने का इरादा है:

Object s = "Java Generics"; 
SubType<Object> x = new SubType<>(s); 
SubType<String> y = x.doMoreSpecific(String.class); 

यहां मैं SubType<V> को लागू करने के लिए संघर्ष करता हूं। क्या मैं एक कार्यान्वयन के रूप में प्रदान करने के लिए चाहते हैं:

public class SubType<V> implements SuperType<V, SubType<V>> { 

    private final V value; 

    public SubType(V value) { this.value = value; } 

    public SubType<V> doSomething() { return this; }; 

    public <W extends V> SubType<W> doMoreSpecific(Class<W> typeToken) { 
     return new SubType<>((W) value); 
    } 
} 

मेरा प्रश्न है:

मैं कैसे प्रकार SuperType<V, S extends SuperType<V, S>> द्वारा SubType<V> implements SuperType<V, SubType<V>> है प्रदान की ताकि कार्यान्वयन में विधि doMoreSpecific() के लिए हस्ताक्षर परिभाषित करना चाहिए स्वीकार्य?

या अन्यथा, कौन सा कार्यान्वयन और इंटरफ़ेस विधि परिभाषा चाल करेगा?

अन्यथा, हम जावा में ऐसा क्यों नहीं कर सकते?

+1

सिर्फ एक commnet, एक अंतरफलक में, सभी तरीकों सार, कर रहे हैं तो स्पष्ट परिभाषा अनावश्यक –

+4

'एस फैली ' मान्य सिंटैक्स जो अपने प्रश्न को समझने के लिए कठिन बना देता है ... – assylias

+0

नहीं है मुझे आशा है कि मैं वाक्यविन्यास त्रुटियों तय । मैं अपने आईडीई में सभी प्रकार को परिभाषित करने के लिए आलसी था :)। माफ़ कीजिये। – Harmlezz

उत्तर

3

निम्नलिखित हस्ताक्षर का उपयोग करना:

<W extends V> SuperType<W, ?> doMoreSpecific(Class<W> typeToken); 

कुछ असुरक्षित मामलों हो सकता है कि हालांकि मैं अभी तक खोजने के लिए नहीं कर पाए हैं, किसी भी आलोचना का स्वागत है! W पैरामीटर प्रकार से अनुमान लगाया जाता है, लेकिन पैरामीटर प्रकार केवल कॉल स्थल पर जाना जाता है:

+0

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

+1

@ हार्मलेज़ - आप पुरानी परिभाषा को 'doMoreSpecific0'' के रूप में रख सकते हैं और 'doMoreSpecific' बस इनवॉक करता है 'doMoreSpecific'; अनुमान खराब लगता है 'टी' पाने के लिए यहां राजा। – ZhongYu

0

आप अपने कोड से पता चलता है कि आप क्या चाहते हैं, तो आप एक टाइप किया विधि है नहीं कर सकते। यानी विधि doMoreSpecific() का संस्करण नहीं है जिसे इंटरफ़ेस SuperType (जिसे कार्यान्वित किया जाना चाहिए) में निर्दिष्ट किया जा सकता है।

निकटतम आप मिल सकता है WSuperType की एक सामान्य प्रकार पैरामीटर बनाने के लिए है, लेकिन फिर अपने कार्यान्वयन ठीक एक वर्ग W, जो typeToken निरर्थक, जो स्पष्ट रूप नहीं है तुम क्या चाहते हो सकता है के लिए काम करेगा।

+1

मैंने अपनी समस्या के बारे में एक सहकर्मी के साथ चर्चा की और उसने मुझे बताया कि जो मुझे पसंद है वह _Java_ में उपलब्ध नहीं है, लेकिन _Scala_ में: एक प्रकार का कन्स्ट्रक्टर। मेरी राय में मुझे जिस समस्या का सामना करना पड़ता है वह यह है कि मैं वापस आने वाले नए प्रकार को बनाने के लिए parametrized प्रकार से _raw type_ निकालने में सक्षम नहीं हूं। उदाहरण के लिए यदि मैं 'एस' से कच्चे प्रकार को निकाल सकता हूं, तो मैं 'कच्चे: एस' कहूंगा कि मैं हस्ताक्षर को निम्नानुसार परिभाषित कर सकता हूं: 'सार्वजनिक कच्चा: एस सुपरटाइप डोरमोर स्पेसिफिक (कक्षा टाइप टोकन) बढ़ाता है;' क्या आप सहमत हैं ? – Harmlezz

0

मैं क्या अपने सटीक इरादा doMoreSpecific पीछे है पता नहीं है, लेकिन अगर यह सिर्फ SubType<String> को SubType<Object> से कास्टिंग है आप निम्न कर सकता है (हालांकि यह बहुत अच्छा अभ्यास नहीं है ...):

Object s = "Java Generics"; 
SubType<Object> x = new SubType<>(s); 
SubType<String> y = (SubType<String>) (SubType<?>) x; 

नोट 1: यह अभी भी एक चेतावनी देगा।

नोट 2: s टाइप String का नहीं है तो यह कास्ट भी काम करेगा! लेकिन y.doSomething() पर कॉल करते समय आपको क्लासकास्ट अपवाद प्राप्त होगा। (जो भी आप उस मामले के लिए अपने उदाहरण में प्राप्त करेंगे)।

उदाहरण के लिए: (बदसूरत) कोड का यह टुकड़ा काम करेगा, भी (लाइनों के अलावा प्रकाश डाला):

ArrayList<?> lo = new ArrayList<Object>(); 
    ArrayList<Integer> li = (ArrayList<Integer>) lo; 
    ArrayList<String> ls = (ArrayList<String>) lo; 

    li.add(5); 
    ls.add("five"); 

    System.out.println(lo);  // prints "[5, five]" 

    System.out.println(li.get(0)); // prints "5" 
    System.out.println(li.get(1)); // ClassCastException 

    System.out.println(ls.get(0)); // ClassCastException 
    System.out.println(ls.get(1)); // prints "five" 

नोट 3: यह पूरी तरह से दिखाता है कि कैसे इस तथ्य काम में जेनरिक: सभी वे करते है स्वचालित रूप से आपके लिए आवश्यक स्थितियों पर डालें।

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