2011-01-20 18 views
15

पर एक विधि निर्दिष्ट करना संभव है जो एक ऑब्जेक्ट देता है जो दो या एकाधिक इंटरफेस लागू करता है?पूर्ण वापसी एकाधिक इंटरफ़ेस

कहते हैं कि हम निम्नलिखित इंटरफेस है:

interface FooBar { 
    [Foo] & [Bar] getFooBar(); 
} 

interface Foo { 
    void doFoo(); 
} 

inteface Bar { 
    void doBar(); 
} 

FooBar का कार्यान्वयन करने वालों विधि getFooBar() कि एक प्रकार है जो Foo fullfills Bar के रूप में रूप में अच्छी तरह का एक उदाहरण देता है प्रदान करने के लिए की जरूरत है।

मैं अब तक क्या करने की कोशिश की जेनरिक के साथ यह करने के लिए है:

interface FooBar { 
    <T extends Foo & Bar> T getFooBar() 
} 

class SomeImplementor implements FooBar { 
    private FooAndBarImpl fSomeField; 

    public <T extends Foo & Bar> T getFooBar() { 
     return fSomeField; 
    } 

} 

यह देखते हुए कि FooAndBarImpl कुछ एक रूपरेखा या पुस्तकालय द्वारा प्रदान प्रकार है और Foo लागू करता है और Bar इस मुझे लगता है कि काम करना चाहिए। हालांकि, ऐसा नहीं है, क्योंकि "FooAndBarImpl को टी में परिवर्तित नहीं किया जा सकता"। ऐसा क्यों है? getFooBar() द्वारा निहित अनुबंध टूटा नहीं है जैसा कि मैंने इसे देखा है।

एक और समाधान Foo और Bar तक फैला हुआ एक नया इंटरफ़ेस परिभाषित करना होगा और इसे रिटर्न प्रकार के रूप में उपयोग करना होगा। getFooBar() कार्यान्वयन में fSomeField के लिए मुझे खाली रैपर लौटने में बहुत अधिक समझ नहीं है।

किसी भी अन्य सलाह और/या स्पष्टीकरण के लिए धन्यवाद।

संपादित करें:

अगर किसी को क्यों जेनरिक दृष्टिकोण काम नहीं करता है समझा सकता है इसकी सराहना करेंगे। मैं बस इसे नहीं देखता हूँ।

+0

मेरा उत्तर अद्यतन के बाद आप अद्यतन, (मैं क्या करने पर विचार) शामिल जेनरिक मुद्दा – davin

उत्तर

13

आप टी एक वर्ग पैरामीटर बना सकते हैं:

class SomeImplementor<T extends Foo & Bar> implements FooBar { 
    private T fSomeField; 

    public T getFooBar() { 
     return fSomeField; 
    } 

} 

क्यों अपनी जेनरिक दृष्टिकोण काम नहीं किया के रूप में। निम्नलिखित दो वर्गों है कि लागू बनाने की सुविधा देता Foo और Bar:

class A implements Bar, Foo{ 
    private int a; 
    ... 
} 
class B implements Bar, Foo{ 
    private String b; 
    ... 
} 
class SomeImplementor implements FooBar { 
    private A someField; 
    public <T extends Foo & Bar> T getFooBar() { 
     return someField; 
    } 
} 

तो अब हम निम्नलिखित निष्पादित करने के लिए सक्षम होना चाहिए: ग्रुप ए का एक उद्देश्य है, जो कोई वैध है

SomeImplementor s = new SomeImplementor(); 
A a = s.getFooBar(); 
B b = s.getFooBar(); 

getFooBar() हालांकि रिटर्न बी टाइप करने के लिए कास्ट करें (String सदस्य कहां से आएगा?), भले ही बी <T extends Foo & Bar> की आवश्यकता को पूरा करता है, यानी वैध T है।

संक्षेप में, संकलक गारंटी नहीं दे सकते प्रकार <T extends Foo & Bar> के हर T प्रकार A की यह करने के लिए एक काम हो सकता है (याद रखें, जेनरिक एक संकलन समय तंत्र है)। आप वास्तव में जो त्रुटि देखते हैं - संकलक दिए गए ए को प्रत्येक मान्य टी में परिवर्तित नहीं कर सकता है।

3

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

मैं इस विकल्प के लिए जाना कहूँगा।

+0

की एक बहुत अच्छी व्याख्या और चूंकि प्रकार एक रूपरेखा द्वारा परिभाषित किया गया है एक आवरण बनाने के लिए? – z00bs

+0

सुनिश्चित नहीं है कि आप एक रैपर द्वारा क्या मतलब है? यदि 'fSomeField' ऐसा कुछ उदाहरण है जो आपके नए संयुक्त FooBar इंटरफ़ेस को लागू करता है, तो रैपर का उपयोग क्यों करें? – Brian

+2

यह प्रकार एक पुस्तकालय द्वारा प्रदान किया जाता है, यानी, मैं कोड नहीं बदल सकता। – z00bs

0

आप फू और बार प्रदान करने के लिए एक कंटेनर वापस कर सकते हैं।

public class Container{ 
    private FooBarBam foobar; 
    public Bar asBar(){ 
     return foobar; 
    } 
    public Foo asFoo(){ 
     return foobar; 
    } 
} 

इस प्रकार आपके कोड को तीसरे इंटरफ़ेस को लागू करने की आवश्यकता नहीं होगी। नकारात्मकता यह है कि यह संकेत की एक अतिरिक्त परत है।

क्यों सामान्य दृष्टिकोण काम नहीं करता है के लिए के रूप में: वहाँ टी के प्रकार प्रदान करने के लिए कोई रास्ता नहीं है और संकलक सिर्फ अपने प्रकार अनुमान नहीं कर सकते, तो हल करने टी संभव नहीं है।

डेविन का जवाब अच्छा दिखता है लेकिन एक सार्वजनिक कक्षा/इंटरफेस की भी आवश्यकता होती है जो काम करने के लिए फू और बार लागू करता है।

अद्यतन:

समस्या संकलक पता नहीं है कि टी के प्रकार FooAndBarImpl होना चाहिए, यह लगता है कि करने के लिए होता है और एक अनुमान लगा संकलक बुरा और अप्रत्याशित कोड होता है।

यहां तक ​​कि & ऑपरेटर समर्थित नहीं होने के कारण सूची का उपयोग करके एक हैक संकलित नहीं होगा। हालांकि इसे कार्यान्वित करना संभव होना चाहिए, ऐसा लगता है कि जेनेरिक वर्तमान में रिटर्न प्रकारों के भीतर कई सीमाओं का समर्थन नहीं करते हैं।

//Does not compile expecting > after Foo 
List<? extends Foo & Bar> getFooBar(){ 
    final List<FooAndBarImpl> l = new ArrayList<FooAndBarImpl>(); 
    l.add(new FooAndBarImpl()); 
    return l; 
} 
+0

यही वह नहीं है जो मुझे नहीं मिलता है: संकलक जानता है कि 'fSomeField' का प्रकार 'फू' और 'बार' लागू करता है और इसलिए यह अनुमान लगाने में सक्षम होना चाहिए कि यह 'फू' और 'बार' का उप प्रकार है, नहीं? – z00bs

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