कुछ कहते हैं कि यह प्रकार और उप-प्रकारों के बीच संबंध के बारे में है, अन्य कहते हैं कि यह प्रकार रूपांतरण के बारे में है और अन्य लोग कहते हैं कि इसका उपयोग यह तय करने के लिए किया जाता है कि कोई विधि अधिलेखित है या अतिभारित है।
ऊपर के सभी।
दिल में, इन शब्दों का वर्णन है कि प्रकार परिवर्तन से उपप्रकार संबंध कैसे प्रभावित होता है। यह है, अगर A
और B
प्रकार हैं, f
एक प्रकार का परिवर्तन है, और ype उपप्रकार संबंध (अर्थात A ≤ B
इसका A
एक उपप्रकार है B
), हमारे पास है
f
सहसंयोजक है अगर A ≤ B
इसका तात्पर्य हैf(A) ≤ f(B)
f
गर्भनिरोधक है अगर A ≤ B
इसका मतलब हैf(B) ≤ f(A)
f
उपरोक्त में से कोई भी नहीं है, तो अपरिवर्तनीय है
आइए एक उदाहरण पर विचार करें। चलो f(A) = List<A>
जहां List
से घोषित किया जाता है
class List<T> { ... }
क्या f
सहसंयोजक, कंट्रावेरिएंट, या अपरिवर्तनीय है? Covariant मतलब यह होगा कि एक List<String>
के एक उप-प्रकार है List<Object>
, contravariant है कि एक List<Object>
के एक उप-प्रकार है List<String>
और अपरिवर्तनीय है कि न तो अन्य की एक उप-प्रकार है, यानी List<String>
और List<Object>
अपरिवर्तनीय प्रकार हैं। जावा में, उत्तरार्द्ध सत्य है, हम कहते हैं (कुछ अनौपचारिक) कि जेनरिक अपरिवर्तनीय हैं।
एक और उदाहरण। चलो f(A) = A[]
। क्या f
सहसंयोजक, कंट्रावेरिएंट, या अपरिवर्तनीय है? यही है, स्ट्रिंग [] वस्तु का एक उपप्रकार [], वस्तु [] स्ट्रिंग का एक उपप्रकार [] है, या न ही दूसरे का उपप्रकार है? (उत्तर: जावा में, सरणियाँ सहसंयोजक हैं)
यह अभी भी अमूर्त था। इसे और अधिक ठोस बनाने के लिए, आइए देखें कि जावा में कौन से ऑपरेशन को उपप्रकार संबंध के संदर्भ में परिभाषित किया गया है। सबसे सरल उदाहरण असाइनमेंट है। बयान
x = y;
संकलन करेगा यदि typeof(y) ≤ typeof(x)
। यही है, हमने सिर्फ बयानों को सीखा है
ArrayList<String> strings = new ArrayList<Object>();
ArrayList<Object> objects = new ArrayList<String>();
जावा में संकलित नहीं करेंगे, लेकिन
Object[] objects = new String[1];
मर्जी।
एक और उदाहरण जहां उपप्रकार संबंध मायने रखता है एक विधि आह्वान अभिव्यक्ति है:
result = method(a);
अनौपचारिक रूप से कहें तो, इस कथन का मूल्यांकन a
विधि के पहले पैरामीटर के मान को निर्दिष्ट करके , फिर विधि के निकाय को निष्पादित करने के लिए किया जाता है, और फिर विधियों को वापस करने के लिए मान प्रदान किया जाता है result
। अंतिम उदाहरण में सादे असाइनमेंट की तरह, "राइट हैंड साइड" "लेफ्ट हैंड साइड" का एक उपप्रकार होना चाहिए, अर्थात यह स्टेटमेंट केवल तभी मान्य हो सकता है यदि typeof(a) ≤ typeof(parameter(method))
और returntype(method) ≤ typeof(result)
। अर्थात्, यदि विधि द्वारा घोषित किया गया है:
Number[] method(ArrayList<Number> list) { ... }
निम्नलिखित में से कोई भी अभिव्यक्ति संकलित नहीं होगी:
Integer[] result = method(new ArrayList<Integer>());
Number[] result = method(new ArrayList<Integer>());
Object[] result = method(new ArrayList<Object>());
परंतु
Number[] result = method(new ArrayList<Number>());
Object[] result = method(new ArrayList<Number>());
मर्जी।
एक और उदाहरण जहां मामलों को घटाया जाना ओवरराइडिंग है। विचार करें:
Super sup = new Sub();
Number n = sup.method(1);
कहाँ पे
class Super {
Number method(Number n) { ... }
}
class Sub extends Super {
@Override
Number method(Number n);
}
अनौपचारिक रूप से, रनटाइम इसे फिर से लिखेगा:
class Super {
Number method(Number n) {
if (this instanceof Sub) {
return ((Sub) this).method(n); // *
} else {
...
}
}
}
संकलित करने के लिए चिह्नित लाइन के लिए, ओवरराइडिंग विधि की विधि पैरामीटर को ओवरराइड विधि के विधि पैरामीटर का एक सुपरपाइप होना चाहिए, और ओवरराइड विधि के एक का उपप्रकार टाइप करें। औपचारिक रूप से, f(A) = parametertype(method asdeclaredin(A))
कम से कम कंट्राविरेंट f(A) = returntype(method asdeclaredin(A))
होना चाहिए , और यदि कम से कम सहसंयोजक होना चाहिए।
ऊपर "कम से कम" नोट करें। वे न्यूनतम आवश्यकताएं हैं जो किसी भी उचित वैधानिक रूप से सुरक्षित ऑब्जेक्ट ओरिएंटेड प्रोग्रामिंग भाषा लागू करेंगी, लेकिन एक प्रोग्रामिंग भाषा अधिक सख्त होने का चुनाव कर सकती है। जावा १.४ के मामले में, पैरामीटर और प्रकार के रिटर्न प्रकार एक जैसे होने चाहिए (जब ओवरराइड करने के तरीके को छोड़कर), जब ओवरराइडिंग के तरीके, यानी parametertype(method asdeclaredin(A)) = parametertype(method asdeclaredin(B))
ओवरराइडिंग। जावा 1.5 के बाद से, ओवरराइड करते समय सहसंयोजक वापसी प्रकारों की अनुमति है, अर्थात निम्नलिखित निम्नलिखित जावा 1.5 में संकलित होगा, लेकिन जावा एक्स में नहीं:
class Collection {
Iterator iterator() { ... }
}
class List extends Collection {
@Override
ListIterator iterator() { ... }
}
मुझे आशा है कि मैंने सब कुछ कवर किया - या बल्कि, सतह को खरोंच कर दिया। फिर भी मुझे उम्मीद है कि यह अमूर्त, लेकिन प्रकार के विचरण की महत्वपूर्ण अवधारणा को समझने में मदद करेगा।