जावा में कॉन्वर्सिस और contravariance के लिए एक अच्छा उदाहरण दिखाएं।जावा में covariance और contravariance का प्रदर्शन?
उत्तर
सहप्रसरण:
class Super {
Object getSomething(){}
}
class Sub extends Super {
String getSomething() {}
}
उप # getSomething covariant है, क्योंकि यह सुपर # getSomething की वापसी प्रकार का एक उपवर्ग रिटर्न (लेकिन Super.getSomething के अनुबंध fullfills())
contravariance
class Super{
void doSomething(String parameter)
}
class Sub extends Super{
void doSomething(Object parameter)
}
उप # DoSomething contrava है रियांत क्योंकि यह सुपर # DoSomething के पैरामीटर के एक सुपर क्लास की एक पैरामीटर लेता है (लेकिन, फिर से, सुपर # DoSomething के अनुबंध fullfills)
नोटिस: इस उदाहरण जावा में काम नहीं करता। जावा कंपाइलर अधिभारित होगा और doSomething() - विधि को ओवरराइड नहीं करेगा। अन्य भाषाएं contravariance की इस शैली का समर्थन करते हैं।
जेनेरिक्स
यह जेनेरिक्स के लिए भी संभव है:
List<String> aList...
List<? extends Object> covariantList = aList;
List<? super String> contravariantList = aList;
अब आप covariantList
के सभी तरीकों कि एक सामान्य पैरामीटर नहीं ले करता है (के रूप में यह कुछ होना चाहिए का उपयोग कर सकते "ऑब्जेक्ट बढ़ाता है"), लेकिन गेटर्स ठीक काम करेंगे (क्योंकि लौटा ऑब्जेक्ट हमेशा "ऑब्जेक्ट" प्रकार होगा)
विपरीत contravariantList
के लिए सच है: आप जेनेरिक पैरामीटर के साथ सभी विधियों तक पहुंच सकते हैं (आपको पता है कि यह "स्ट्रिंग" का सुपरक्लास होना चाहिए, इसलिए आप हमेशा एक पास कर सकते हैं), लेकिन कोई गेटर्स नहीं (लौटाया गया प्रकार किसी भी अन्य सुपरटेप का हो सकता है स्ट्रिंग का)
Liskov substitution principle पर देखें। असल में, यदि कक्षा बी कक्षा ए को बढ़ाता है तो आपको जब भी ए की आवश्यकता होती है तो बी का उपयोग करने में सक्षम होना चाहिए।
इस के साथ सवाल का जवाब नहीं दे रहा है और भ्रामक है। एक वैरिएंट सिस्टम तैयार करना पूरी तरह से संभव होगा जो अर्थपूर्ण शुद्धता को तोड़ता है और इसलिए एलएसपी का उल्लंघन करता है। –
यह 'अनुबंध संस्करण' के मामले में नहीं है। 'super.do कुछ (" स्ट्रिंग ")' 's.do कुछ (ऑब्जेक्ट) 'द्वारा प्रतिस्थापित नहीं किया जा सका। – zinking
सह-भिन्नता: Iterable और Iterator। यह लगभग सह-संस्करण Iterable
या Iterator
को परिभाषित करने के लिए लगभग हमेशा समझ में आता है। Iterator<? extends T>
का उपयोग Iterator<T>
के रूप में किया जा सकता है - एकमात्र जगह जहां टाइप पैरामीटर दिखाई देता है वह next
विधि से वापसी प्रकार है, इसलिए इसे T
पर सुरक्षित रूप से अप-कास्ट किया जा सकता है। लेकिन अगर आपके पास S
T
फैला है, तो आप प्रकार के चर के लिए Iterator<S>
असाइन भी कर सकते हैं। उदाहरण के लिए यदि आप एक खोज विधि को परिभाषित कर रहे हैं:
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)
contravariance का पहला उदाहरण जावा में काम नहीं करता है। उप वर्ग में कुछ() एक अधिभार है, ओवरराइड नहीं है। वास्तव में –
। जावा subtyping में contravariant तर्क का समर्थन नहीं करता है। केवल चिंता विधि प्रकार के प्रकार के लिए covariance (जैसा कि पहले उदाहरण में)। –
ग्रेट उत्तर। कॉन्वर्सिस मेरे लिए तार्किक लग रहा है। लेकिन क्या आप मुझे जेएलएस में एक अनुच्छेद बता सकते हैं जो contravariance का वर्णन करता है? Sub.do कुछ क्यों बुलाया जाता है? – Mikhail