जवाबों:
सहप्रसरण:
class Super {
Object getSomething(){}
}
class Sub extends Super {
String getSomething() {}
}
सब # getSomething कोवेरिएंट है क्योंकि यह सुपर # getSomething के रिटर्न प्रकार का एक उपवर्ग देता है (लेकिन Super.getSomething () के अनुबंध को पूर्ण करता है)
contravariance
class Super{
void doSomething(String parameter)
}
class Sub extends Super{
void doSomething(Object parameter)
}
उप # doSomething विरोधाभासी है क्योंकि यह Super # doSomething (लेकिन फिर, Super # doSomething के अनुबंध को पूरा करता है) के पैरामीटर के एक सुपरक्लास का पैरामीटर लेता है
सूचना: यह उदाहरण जावा में काम नहीं करता है। जावा संकलक अधिभार और doSomething () - विधि को ओवरराइड नहीं करेगा। अन्य भाषाएँ विरोधाभासी इस शैली का समर्थन करती हैं।
जेनेरिक्स
जेनरिक के लिए भी यह संभव है:
List<String> aList...
List<? extends Object> covariantList = aList;
List<? super String> contravariantList = aList;
अब आप सभी तरीकों का उपयोग कर सकते हैं, covariantList
जेनेरिक पैरामीटर नहीं लेते हैं (जैसा कि कुछ "ऑब्जेक्ट का विस्तार" होना चाहिए), लेकिन गेटर्स ठीक काम करेंगे (जैसा कि लौटी हुई वस्तु हमेशा "ऑब्जेक्ट" प्रकार की होगी)
इसके विपरीत यह सच है contravariantList
: आप सभी तरीकों को जेनेरिक मापदंडों के साथ एक्सेस कर सकते हैं (आप जानते हैं कि यह "स्ट्रिंग" का सुपरक्लास होना चाहिए, ताकि आप हमेशा एक पास कर सकें), लेकिन कोई भी गेटर्स (लौटा हुआ प्रकार स्ट्रिंग के किसी अन्य सुपरटेप का नहीं हो सकता है) )
सह-विचरण: Iterable and Iterator। यह लगभग हमेशा एक सह-संस्करण Iterable
या परिभाषित करने के लिए समझ में आता है Iterator
। Iterator<? extends T>
बस के रूप में इस्तेमाल किया जा सकता है Iterator<T>
- एक ही स्थान जहां टाइप पैरामीटर दिखाई देता है next
विधि से वापसी प्रकार है , इसलिए इसे सुरक्षित रूप से अप-कास्ट किया जा सकता है T
। लेकिन अगर आपके पास S
विस्तार है T
, तो आप Iterator<S>
एक प्रकार के चर को भी असाइन कर सकते हैं Iterator<? extends T>
। उदाहरण के लिए यदि आप खोज विधि को परिभाषित कर रहे हैं:
boolean find(Iterable<Object> where, Object what)
आप इसे कॉल नहीं कर पाएंगे List<Integer>
और 5
इसलिए इसे बेहतर तरीके से परिभाषित किया जाएगा
boolean find(Iterable<?> where, Object what)
कंट्रा-विचरण: तुलनित्र। यह लगभग हमेशा उपयोग करने के लिए समझ में आता है Comparator<? super T>
, क्योंकि यह बस के रूप में इस्तेमाल किया जा सकता है Comparator<T>
। प्रकार पैरामीटर केवल compare
विधि पैरामीटर प्रकार के रूप में प्रकट होता है , इसलिए T
इसे सुरक्षित रूप से पारित किया जा सकता है। उदाहरण के लिए यदि आपके पास एक है DateComparator implements Comparator<java.util.Date> { ... }
और आप List<java.sql.Date>
उस तुलनित्र ( java.sql.Date
एक उप-वर्ग java.util.Date
) के साथ छांटना चाहते हैं , तो आप इसके साथ कर सकते हैं:
<T> void sort(List<T> what, Comparator<? super T> how)
लेकिन साथ नहीं
<T> void sort(List<T> what, Comparator<T> how)
को देखो Liskov प्रतिस्थापन सिद्धांत । वास्तव में, यदि क्लास बी क्लास ए का विस्तार करता है तो आपको ए की आवश्यकता होने पर बी का उपयोग करने में सक्षम होना चाहिए।
contra variant
कहने का मामला नहीं है । super.doSomething("String")
द्वारा प्रतिस्थापित नहीं किया जा सकता है sub.doSomething(Object)
।