2012-12-05 14 views
6

मेरे पास कुछ कक्षा public class myClass implements A, B है जहां ए और बी दोनों में public int doSomething(); विधि है, लेकिन A.doSomething इंटरफ़ेस द्वारा B.doSomething से कुछ अलग करने के लिए निर्दिष्ट किया गया है।दो इंटरफेस एक ही हस्ताक्षर के साथ विधियों को निर्दिष्ट करते हैं, लेकिन अलग-अलग व्यवहार के लिए निर्दिष्ट हैं?

मैंने Two interfaces with same method signature implemented in Java class पढ़ा है, लेकिन यह वास्तव में मेरी समस्या का समाधान नहीं करता है, क्योंकि विधियों को एक ही काम करने के लिए ओवरराइड किया जाता है, लेकिन जैसा कि मैंने उपरोक्त कहा है, मेरा प्रश्न यह है कि जब वे अंतर करने के लिए इंटरफेस में निर्दिष्ट होते हैं बातें। जबकि B.doSomething() एक अपवाद फेंकने के लिए माना जाता है, और तरीकों कि उन्हें पैरामीटर के रूप में लेने के लिए अपेक्षा की जाती है के लिए या तो एक wold कारण समस्याओं का उल्लंघन करने

उदाहरण के लिए, मान लीजिए A.doSomething(), 0 वापस जाने के लिए माना जाता है।

क्या जावा में ऐसा करने का कोई तरीका है? यदि हां, तो वास्तव में यह कैसे करेगा?

+0

आप कोई दूसरा रास्ता हस्ताक्षर से एक को बदलने के लिए की तुलना में है ओवरलोड। आपके पास एक ही कक्षा में समान हस्ताक्षर के साथ दो विधियां नहीं हो सकती हैं। –

+0

.NET में आप इंटरफ़ेस सदस्यों को स्पष्ट रूप से कार्यान्वित कर सकते हैं, ताकि जब तक कि विशेष इंटरफ़ेस प्रकार पर उदाहरण डाला न जाए, तब तक वे निजी दिखाई देते हैं। तो आप स्पष्ट रूप से दोनों कार्यान्वयन को लागू कर सकते हैं। क्या जावा का एक समान निर्माण है? – jrummell

+0

@jrummell नहीं, इंटरफेस से विधियों * को सार्वजनिक घोषित किया जाना चाहिए। साथ ही, सटीक उसी हस्ताक्षर के साथ दो विधियां (वापसी प्रकार, नाम, और पैरामीटर/पैरामीटर ऑर्डर सभी समान हैं), भले ही एक्सेसर्स अलग हैं, और यहां तक ​​कि यदि कोई स्थिर रूप से घोषित किया गया है और अन्य गैर-स्थैतिक * आपको कंपाइलर त्रुटियां – Brian

उत्तर

1

आप ऐसा करने के लिए Proxy उदाहरण का उपयोग करने में सक्षम हो सकते हैं।

InvocationHandler है कि आप को देखने के लिए जो इंटरफ़ेस विधि कॉल और अपने ऑब्जेक्ट के अंदर उचित विधि को सौंपने के लिए किया जा रहा है की जाँच करेगा लिखने Proxy पर जानकारी के लिए this question देखें (विशेष रूप से, दूसरा जवाब का हिस्सा है।)।

public class MyClass { 
    // Note that we aren't implementing the interfaces anymore 

    public int doSomethingForA() { 
     return 0; 
    } 

    public int doSomethingForB() { 
     throw new IllegalArgumentException(); 
    } 
} 

फिर अपने InvocationHandler:

public class MyClassInvocationHandler implements InvocationHandler { 

    private MyClass target; 

    public MyClassInvocationHandler(MyClass target) { 
     this.target = target; 
    } 

    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { 
     try { 
      if (method.getDeclaringClass().equals(InterfaceA.class)) 
       return MyClass.getMethod("doSomethingForA").invoke(target, args); 
      else if (method.getDeclaringClass().equals(InterfaceB.class)) 
       return MyClass.getMethod("doSomethingForB").invoke(target, args); 
      else 
       throw new UnsupportedOperationException("Unsupported interface: " + method.getDeclaringClass()); 
     } catch (NoSuchMethodException ex) { 
      throw new UnsupportedOperationException("Method not found", ex); 
     } catch (IllegalAccessException ex) { 
      throw new UnsupportedOperationException("Method was not public", ex); 
     } catch (InvocationTargetException ex) { 
      // May throw a NullPointerException if there is no target exception 
      throw ex.getTargetException(); 
     } 
    } 
} 

तब प्रॉक्सी बनाने के लिए, आप दोनों इंटरफेस में पारित करेंगे:

Proxy.newProxyInstance(null, new Class<?>[] { InterfaceA.class, InterfaceB.class }, new MyClassInvocationHandler(mc)); 

मैं लगता यहाँ अपने कार्यान्वयन दिखता है की तरह है यह काम करेगा। जब आप इसे एक इंटरफेस या अन्य का उपयोग करते हुए कहते हैं:

MyClass mc = new MyClass(); 
Object proxy = Proxy.newProxyInstance(null, new Class<?>[] { InterfaceA.class, InterfaceB.class }, new MyClassInvocationHandler(mc)); 
InterfaceA a = (InterfaceA) proxy; 
a.doSomething(); 
InterfaceB b = (InterfaceB) proxy; 
b.doSomething(); 

तो यह चाहिए विभिन्न घोषित वर्गों के साथ Method वस्तुओं में पास। मुझे यकीन नहीं है कि यह इस तरह काम करता है, इसलिए इसका परीक्षण करने की आवश्यकता होगी।

+0

** अस्वीकरण: ** यह वास्तव में * हैकी है और आपको केवल यह करना चाहिए यदि यह बिल्कुल जरूरी है, यानी आप किसी भी इंटरफेस को नहीं बदल सकते हैं या कुछ जंगली कारणों से दो अलग-अलग कार्यान्वयन नहीं कर सकते डेटा बाधाएं – Brian

4

अनुसार JLS

interface Fish { int getNumberOfScales(); } 
interface StringBass { double getNumberOfScales(); } 
class Bass implements Fish, StringBass { 
    // This declaration cannot be correct, no matter what type is used. 
    public ??? getNumberOfScales() { return 91; } 
} 

यह असंभव है एक विधि नामित getNumberOfScales जिनके हस्ताक्षर घोषित करने और वापस जाने के प्रकार के लिए दोनों में से जो के साथ संगत कर रहे हैं (यह आप क्या चाहते हैं, सटीक नहीं हो सकता है की तरह समान मामला है) इंटरफ़ेस में घोषित विधियों और इंटरफ़ेस स्ट्रिंगबास में, क्योंकि एक वर्ग में एक ही हस्ताक्षर और विभिन्न आदिम रिटर्न प्रकार (§8.4) के साथ कई विधियां नहीं हो सकती हैं।

जब तक आप प्रॉक्सी (या) विधि हस्ताक्षर जोड़कर अपना डिज़ाइन बदल नहीं लेते हैं, तो आप जो भी उम्मीद कर रहे हैं वह करना संभव नहीं है।

0

यह तभी संभव (विभिन्न वापसी प्रकार) यदि आप तरीकों

public interface IA { 
int doSomething(); 
} 

public interface IB { 
void doSomething(String value) throws Exception; 
} 

public class B implements IB, IA{ 
    @Override 
    public void doSomething(String value) throws Exception { 
     throw new Exception(value); 
    } 

    @Override 
    public int doSomething() { 
     return 0; 
    } 
} 
संबंधित मुद्दे

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