ओवरक्लाइडिंग विधियों को तर्क के रूप में पास करके उपवर्ग ऑब्जेक्ट जहां सुपरपेप की अपेक्षा की जाती है


12

मैं सिर्फ जावा सीख रहा हूं, और अभ्यास करने वाला प्रोग्रामर नहीं हूं।

मैं जिस पुस्तक का अनुसरण कर रहा हूं वह कहती है कि किसी विधि को ओवरराइड करते समय, तर्क प्रकार समान होना चाहिए, लेकिन रिटर्न प्रकार पॉलीमॉर्फिक संगत हो सकते हैं।

मेरा सवाल यह है कि ओवरराइडिंग पद्धति को पारित किए गए तर्कों को सुपर-टाइप की उप-प्रकार की उम्मीद नहीं की जा सकती है?

ओवरलोड विधि में, मैं जिस भी विधि पर ऑब्जेक्ट को कॉल करता हूं, उसे ऑब्जेक्ट पर परिभाषित करने की गारंटी दी जाती है।


सुझाए गए डुप्लिकेट पर नोट्स:

पहला सुझाव वर्ग पदानुक्रम और जहां कार्यक्षमता डाल करने के बारे में प्रतीत होता है। मेरा प्रश्न इस बात पर अधिक केंद्रित है कि भाषा पर प्रतिबंध क्यों है।

दूसरा सुझाव है कि कैसे मैं क्या पूछ रहा हूँ करने के लिए, लेकिन नहीं बताते हैं क्यों कि जिस तरह से किया जाना यह किया है। मेरा सवाल क्यों पर केंद्रित है।


1
पहले से पूछे गए सवाल के जवाब में कहा गया : "यह आमतौर पर लिस्कोव सबस्टीट्यूशन सिद्धांत (एलएसपी) में विफल माना जाता है, क्योंकि अतिरिक्त बाधा यह बनाती है कि बेस क्लास ऑपरेशन हमेशा व्युत्पन्न वर्ग के लिए उपयुक्त नहीं होते ..."
gnat


@ प्रश्न यह नहीं है कि क्या तर्कों के लिए अधिक विशिष्ट उपप्रकारों की आवश्यकता होती है जो कुछ कंप्यूटर सिद्धांत का उल्लंघन करता है, प्रश्न यह है कि क्या यह संभव है, जो एडलोरोज़ो ने उत्तर दिया।
user949300

जवाबों:


18

आपके प्रश्न में शुरू में आपके द्वारा संदर्भित अवधारणा को सहसंयोजक रिटर्न प्रकार कहा जाता है ।

सहसंयोजक वापसी प्रकार काम करते हैं क्योंकि एक विधि कुछ प्रकार के ऑब्जेक्ट को वापस करने के लिए होती है और ओवरराइडिंग तरीके वास्तव में इसका एक उपवर्ग वापस कर सकते हैं। जावा जैसी भाषा के Sउप- नियमों के आधार पर, यदि इसका उप-प्रकार है T, तो जहां भी Tहम प्रकट होते हैं, हम उसे पास कर सकते हैं S

जैसे कि एक ऐसी Sविधि को ओवरराइड करके वापस लौटना सुरक्षित है, जिसकी उम्मीद की जाती है T

आपका सुझाव यह स्वीकार करने के लिए कि एक ओवरराइडिंग विधि, उन तर्कों का उपयोग करती है जो ओवरराइड विधि द्वारा अनुरोधित लोगों के उपप्रकार हैं, यह अधिक जटिल है क्योंकि यह टाइप सिस्टम में असत्यता की ओर जाता है।

एक हाथ से, ऊपर वर्णित एक ही उप-नियम द्वारा, सबसे अधिक संभावना है कि यह पहले से ही आप क्या करना चाहते हैं के लिए काम करता है। उदाहरण के लिए

interface Hunter {
   public void hunt(Animal animal);
}

कुछ भी नहीं इस वर्ग के कार्यान्वयन को किसी भी प्रकार के जानवर को प्राप्त करने से रोकता है, क्योंकि यह पहले से ही आपके प्रश्न में मानदंडों को संतुष्ट करता है।

लेकिन मान लें कि जैसा आपने सुझाया था, हम इस विधि को ओवरराइड कर सकते हैं:

class MammutHunter implements Hunter {
  @Override
  public void hunt(Mammut animal) {
  }
}

यहाँ मज़ेदार हिस्सा है, अब आप यह कर सकते हैं:

AnimalHunter hunter = new MammutHunter();
hunter.hunt(new Bear()); //Uh oh

AnimalHunterआप के सार्वजनिक इंटरफ़ेस के अनुसार किसी भी जानवर का शिकार करने में सक्षम होना चाहिए, लेकिन आपके कार्यान्वयन के अनुसार MammutHunterआप केवल Mammutवस्तुओं को स्वीकार करते हैं। इसलिए ओवरराइड विधि सार्वजनिक इंटरफ़ेस को संतुष्ट नहीं करती है। हमने यहां टाइप सिस्टम की ध्वनि को तोड़ दिया।

आप जेनेरिक का उपयोग करके आप जो चाहें लागू कर सकते हैं।

interface AnimalHunter<T extends Animal> {
   void hunt(T animal);
}

तब आप अपने MammutHunter को परिभाषित कर सकते हैं

class MammutHunter implements AnimalHunter<Mammut> {
   void hunt(Mammut m){
   }
}

और जेनेरिक कोवरिएनस और कंट्रोवर्सी का उपयोग करके आप आवश्यक होने पर नियमों को अपने पक्ष में आराम कर सकते हैं। उदाहरण के लिए हम यह सुनिश्चित कर सकते हैं कि एक स्तनपायी शिकारी केवल दिए गए संदर्भ में शिकार का शिकार कर सकता है:

AnimalHunter<? super Feline> hunter = new MammalHunter();
hunter.hunt(new Lion());
hunter.hunt(new Puma());

MammalHunterलागू करने की आपूर्ति AnimalHunter<Mammal>

उस स्थिति में यह स्वीकार नहीं किया जाएगा:

hunter.hunt(new Mammut()):

यहां तक ​​कि जब स्तनधारी स्तनधारी होते हैं तो यह हमारे द्वारा उपयोग किए जा रहे विरोधाभासी प्रकार पर प्रतिबंध के कारण स्वीकार नहीं किया जाएगा। इसलिए, आप अभी भी कुछ नियंत्रकों को उन प्रकारों पर कर सकते हैं जो आपके द्वारा उल्लिखित चीजों की तरह हैं।


3

समस्या यह नहीं है कि आप तर्क के रूप में दिए गए ऑब्जेक्ट के साथ ओवरराइडिंग विधि में क्या करते हैं। समस्या यह है कि आपकी पद्धति का उपयोग करके कोड को किस प्रकार के तर्कों को आपकी विधि को खिलाने की अनुमति है।

एक ओवरराइडिंग विधि को ओवरराइड विधि के अनुबंध को पूरा करना चाहिए। यदि ओवरराइड की गई विधि कुछ वर्ग के तर्कों को स्वीकार करती है और आप इसे एक ऐसी विधि से ओवरराइड करते हैं जो केवल एक उपवर्ग को स्वीकार करती है, तो यह अनुबंध को पूरा नहीं करती है। इसलिए यह मान्य नहीं है।

अधिक विशिष्ट प्रकार के तर्क के साथ किसी विधि को ओवरराइड करना ओवरलोडिंग कहलाता है । यह एक ही नाम के साथ एक विधि को परिभाषित करता है लेकिन एक अलग या अधिक विशिष्ट प्रकार के तर्क के साथ। एक अधिभार विधि मूल विधि के अलावा उपलब्ध है। किस विधि को कहा जाता है यह संकलन समय पर ज्ञात प्रकार पर निर्भर करता है। एक विधि को ओवरलोड करने के लिए आपको @Override एनोटेशन को छोड़ना होगा।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.