2010-03-10 21 views
29

पर विचार करें मैं निम्नलिखित इंटरफेस है:जावा इंटरफेस और वापसी प्रकार

public interface A { public void b(); } 

हालांकि मैं वर्गों है कि इसे लागू के प्रत्येक चाहते विधि ख के लिए एक अलग वापसी प्रकार है करने के लिए()।

उदाहरण:

public class C { 
    public C b() {} 
} 

public class D { 
    public D b() {} 
} 

मैं अपने इंटरफेस कैसे परिभाषित करेंगे तो यह है कि यह संभव था?

उत्तर

45

वापसी प्रकार वर्ग है कि इंटरफ़ेस को लागू करता है के प्रकार होना चाहिए, तो क्या आप चाहते हैं कहा जाता है एक F-bounded type:

public interface A<T extends A<T>>{ public T b(); } 

public class C implements A<C>{ 
    public C b() { ... } 
} 

public class D implements A<D>{ 
    public D b() { ... } 
} 

शब्दों में, A एक प्रकार पैरामीटर T उस पर ले जाएगा की घोषणा कर रहा है प्रत्येक ठोस प्रकार का मान जो A लागू करता है। यह आमतौर पर clone() या copy() जैसी चीजों को घोषित करने के लिए उपयोग किया जाता है जो अच्छी तरह से टाइप किए जाते हैं। एक और उदाहरण के रूप में, यह घोषणा करने के लिए java.lang.Enum द्वारा उपयोग किया जाता है कि प्रत्येक enum विरासत में compareTo(E) विधि केवल उस विशेष प्रकार के अन्य enums पर लागू होती है।

यदि आप अक्सर इस पैटर्न का उपयोग करते हैं, तो आप thisT टाइप करने के लिए परिदृश्य में भाग लेंगे। पहली नज़र में यह स्पष्ट प्रतीत हो सकता है कि यह है, लेकिन आपको वास्तव में abstract T getThis() विधि घोषित करने की आवश्यकता होगी, जिसे कार्यान्वयनकर्ताओं को return this के रूप में छोटे पैमाने पर कार्यान्वित करना होगा।

[1] जैसा कि टिप्पणीकारों ने इंगित किया है, X implements A<Y> जैसे X और Y ठीक से सहयोग करने के लिए कुछ स्नीकी करना संभव है। T getThis() विधि की उपस्थिति यह भी स्पष्ट करती है कि XA इंटरफ़ेस के लेखक के इरादे को बाधित कर रहा है।

+0

+! - बहुत अच्छा। मैंने यहाँ कुछ सीखा। धन्यवाद, मैट। – duffymo

+0

ऑफ-विषय: इस तरह वाक्यविन्यास यही कारण है कि मैं जितना संभव हो सके जेनरेटेड एपीआई बनाने से बचने के लिए अपना सर्वश्रेष्ठ प्रयास कर रहा हूं। – dimitarvp

+1

अच्छा उत्तर (और जेनेरिक की शक्ति का एक बड़ा उदाहरण), लेकिन यह प्रोग्रामर को सी लागू करने से रोकता नहीं है (मेरा दूसरा जवाब देखें)। – Cam

34

जेनिक्स।

public interface A<E>{ 
    public E b(); 
} 

public class C implements A<C>{ 
    public C b(){ 
     return new C(); 
    } 
} 

public class D implements A<D>{ 
    public D b(){ 
     return new D(); 
    } 
} 

अधिक जानकारी के लिए जेनरिक अप खोजें, लेकिन (बहुत) मूल रूप से, क्या हो रहा है कि A छोड़ देता है E के लागू करने clases (C और D) तक टाइप है।

तो मूल रूप से ए को पता नहीं है (और यह नहीं पता है कि किसी भी कार्यान्वयन में ई क्या हो सकता है।

+3

मुझे उस "उत्तर" के रूप में चिह्नित एक से अधिक पसंद है, क्योंकि आपको इस तथ्य पर भरोसा नहीं करना है कि कार्यान्वयनकर्ताओं को वास्तव में जनरेटेड घोषणा में अपना वर्ग नाम शामिल होगा। उस पर मुझ से अंगूठे ऊपर। – dimitarvp

+0

यह किसी भी वापसी प्रकार –

2

जावा supports covariant return types के बाद से (जावा 1.5 के बाद से), तो आप कर सकते हैं:

public interface A { public Object b(); } 
+7

के लिए काम नहीं करता है। आप चाहते हैं कि आपका इंटरफेस जितना संभव हो सके आकस्मिक दुरुपयोग के लिए छोटे कमरे के रूप में छोड़ दें। इस तरह की विधि के साथ, 'ए' को लागू करते समय प्रोग्रामर को गलती करना बहुत आसान होगा। – Cam

+0

प्रश्न ओवरराइडिंग प्रकारों पर स्पष्ट रूप से किसी भी प्रतिबंध को निर्दिष्ट नहीं किया था। बेशक, यदि ऐसे प्रतिबंध मौजूद हैं, तो उन्हें एक इंटरफ़ेस के साथ लागू करना चाहिए जहां संभव हो। – meriton

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