क्यों एक इंटरफ़ेस को लागू करने वाला एक सार वर्ग इंटरफ़ेस के तरीकों में से एक की घोषणा / कार्यान्वयन को याद कर सकता है?


123

एक जिज्ञासु बात जावा में तब होती है जब आप एक इंटरफ़ेस को लागू करने के लिए एक सार वर्ग का उपयोग करते हैं: इंटरफ़ेस के कुछ तरीके पूरी तरह से गायब हो सकते हैं (यानी न तो एक सार घोषणा या वास्तविक कार्यान्वयन मौजूद है), लेकिन कंपाइलर शिकायत नहीं करता है।

उदाहरण के लिए, इंटरफ़ेस दिया गया:

public interface IAnything {
  void m1();
  void m2();
  void m3();
}

निम्नलिखित सार वर्ग चेतावनी या त्रुटि के बिना आसानी से संकलित हो जाता है:

public abstract class AbstractThing implements IAnything {
  public void m1() {}
  public void m3() {}
}

क्या आप व्यख्या कर सकते हैं?


2
एक अमूर्त वर्ग की वस्तु नहीं बना सकता है। इसलिए, जब तक कि एक अमूर्त वर्ग के लिए कार्यान्वयन प्रदान नहीं किया जाता है, तब तक IAnything के लिए ऑब्जेक्ट नहीं बनाए जा सकते हैं। इसलिए यह कंपाइलर के लिए बिल्कुल ठीक है। कंपाइलर को उम्मीद है कि, किसी भी गैर-सार वर्ग जो IAnything को लागू करता है, IAnything से बाहर घोषित सभी विधियों को लागू करना चाहिए। और चूंकि किसी को ऑब्जेक्ट बनाने में सक्षम होने के लिए AbstractThing का विस्तार और कार्यान्वयन करना है, इसलिए कंपाइलर एक त्रुटि फेंक देगा, यदि वह कार्यान्वयन AbstractThing द्वारा छोड़े गए IAnything के तरीकों को लागू नहीं करता है।
वनाग्सेस

मेरे पास एक ठोस वर्ग था जो एक समान परिदृश्य में अपने स्वयं के "AbstractThing" का विस्तार कर रहा था, और भले ही मैंने इंटरफ़ेस में से किसी एक तरीके को लागू नहीं किया था, यह अनावश्यक रूप से संकलन था। अब यह वही कर रहा है जिसकी मुझे उम्मीद है, लेकिन मैं यह पता नहीं लगा सकता कि इससे पहले सफल होने के लिए क्या कारण था। मुझे संदेह है कि मैं :wफ़ाइलों में से एक नहीं था ।
ब्रैडेन बेस्ट

आप इसी तरह के प्रश्न के लिए awer देख सकते हैं stackoverflow.com/questions/8026580/…
Do Nhu Vy

जवाबों:


155

ऐसा इसलिए है क्योंकि यदि कोई वर्ग अमूर्त है, तो परिभाषा के अनुसार आपको तात्कालिकता के लिए उपवर्ग बनाने की आवश्यकता होती है। उप-वर्ग की आवश्यकता होगी (संकलक द्वारा) किसी भी इंटरफ़ेस विधियों को लागू करने के लिए जो अमूर्त वर्ग को छोड़ देता है।

अपने उदाहरण कोड के बाद, विधि AbstractThingको लागू किए बिना एक उपवर्ग बनाने का प्रयास करें m2और देखें कि संकलक आपको क्या त्रुटियां देता है। यह आपको इस पद्धति को लागू करने के लिए मजबूर करेगा।


1
मुझे लगता है कि कंपाइलर को अभी भी अमूर्त वर्गों के बारे में चेतावनी फेंकनी चाहिए जो इंटरफेस को अपूर्ण रूप से लागू करते हैं, सिर्फ इसलिए कि तब आपको उपवर्ग में जो चाहिए उसे देखने के लिए 1 के बजाय 2 कक्षा परिभाषाओं से गुजरना होगा। हालांकि यह एक भाषा / संकलक सीमा है।
वर्कमाड 3

3
यह एक अच्छा विचार नहीं होगा, क्योंकि आमतौर पर बहुत सारे अमूर्त वर्ग हो सकते हैं और 'झूठी' चेतावनियाँ जल्द ही आपको अभिभूत कर देंगी, जिससे आपको 'सही' चेतावनियाँ याद आती हैं। यदि आप इसके बारे में सोचते हैं, तो 'अमूर्त' कीवर्ड विशेष रूप से उस वर्ग के लिए चेतावनी के संकलनकर्ता को बताने के लिए है।
बेलुगाब

4
@ काममाड - यदि आपके पास इंटरफ़ेस विधियों के सबसेट के लिए सामान्य कार्यान्वयन है, तो यह एक अलग आधार वर्ग में कारक को बेहतर बनाता है (DRY एक स्थान-कोड को ट्रम्प करता है)
Gishu

4
यह करने के लिए खतरनाक होगा की आवश्यकता होती है एक अमूर्त वर्ग में खाली विधि कार्यान्वयन डाल करने के लिए आप। यदि आपने ऐसा किया है तो उपवर्गों के कार्यान्वयनकर्ता इस गैर-व्यवहार को संकलित किए बिना बताएंगे कि उन्हें कोई समस्या है।
छिपकली

8
मुझे लगता है कि जो वर्कमैड सुझाव दे रहा है, वह यह है कि आप एब्स्ट्रैक्ट क्लास में बिना मेथड बॉडी के तरीकों को परिभाषित करते हैं और उन्हें एब्सट्रैक्ट करते हैं। मुझे एक बुरा विचार नहीं लगता।
डोरनल

33

पूरी तरह से ठीक।
आप अमूर्त कक्षाओं को तात्कालिक नहीं कर सकते हैं .. लेकिन एम 1 () और एम 3 () के लिए घर के सामान्य कार्यान्वयन के लिए सार कक्षाओं का उपयोग किया जा सकता है।
तो अगर एम 2 () कार्यान्वयन प्रत्येक कार्यान्वयन के लिए अलग है, लेकिन एम 1 और एम 3 नहीं हैं। आप अलग अलग IAnything कार्यान्वयन बना सकते हैं बस अलग-अलग m2 कार्यान्वयन के साथ और AbstractThing से प्राप्त करें - DRY सिद्धांत का सम्मान करते हुए। यदि इंटरफ़ेस पूरी तरह से एक अमूर्त वर्ग के लिए कार्यान्वित किया जाता है, तो वैध है।

अद्यतन : दिलचस्प बात यह है कि मुझे लगता है कि C # इसे एक संकलित त्रुटि के रूप में लागू करता है। आपको इस विधि में हस्ताक्षर करने के लिए मजबूर किया गया है और उन्हें 'एब्सट्रैक्ट पब्लिक क्लास' में 'एब्सट्रैक्ट पब्लिक' के साथ प्रीफ़िक्स किया जा रहा है .. (कुछ और हर रोज़ :)


7

कोई बात नहीं। उपरोक्त समझने के लिए, आपको पहले अमूर्त कक्षाओं की प्रकृति को समझना होगा। वे उस संबंध में इंटरफेस के समान हैं। इस बारे में ओरेकल का यही कहना है

सार वर्ग इंटरफेस के समान हैं। आप उन्हें तुरंत नहीं कर सकते हैं, और उनमें कार्यान्वयन के साथ या बिना घोषित तरीकों का मिश्रण हो सकता है।

तो आपको यह सोचना होगा कि जब एक इंटरफ़ेस दूसरे इंटरफ़ेस का विस्तार करता है तो क्या होता है। उदाहरण के लिए ...

//Filename: Sports.java
public interface Sports
{
   public void setHomeTeam(String name);
   public void setVisitingTeam(String name);
}

//Filename: Football.java
public interface Football extends Sports
{
   public void homeTeamScored(int points);
   public void visitingTeamScored(int points);
   public void endOfQuarter(int quarter);
}

... जैसा कि आप देख सकते हैं, यह भी पूरी तरह से ठीक संकलित करता है। केवल इसलिए, एक अमूर्त वर्ग की तरह, एक इंटरफ़ेस तुरंत नहीं किया जा सकता है। तो, इसके "मूल" से तरीकों का स्पष्ट रूप से उल्लेख करने की आवश्यकता नहीं है। हालाँकि, सभी पैरेंट विधि हस्ताक्षर करते हैं। यह स्पष्ट रूप से विस्तृत इंटरफ़ेस या अमूर्त वर्ग को लागू करने का एक हिस्सा बन गया है। इसलिए, एक बार एक उचित वर्ग (एक जिसे तत्काल किया जा सकता है) उपरोक्त का विस्तार करता है, यह सुनिश्चित करने के लिए आवश्यक होगा कि हर एक अमूर्त पद्धति को लागू किया जाए।

उम्मीद है कि मदद करता है ... और अल्लाह 'आलम!


यह एक दिलचस्प बात है। यह मुझे लगता है कि "अमूर्त वर्ग" वास्तव में "ठोस इंटरफेस" हैं, अर्थात कुछ ठोस तरीकों के साथ कक्षाओं के बजाय कुछ ठोस तरीकों के साथ इंटरफेस।
Giulio Piancastelli

... वास्तव में दोनों का एक सा। लेकिन एक बात सुनिश्चित करने के लिए, वे तात्कालिक नहीं हैं।
आभारी

4

इंटरफ़ेस का मतलब एक ऐसा वर्ग है जिसमें इसकी पद्धति का कोई कार्यान्वयन नहीं है, लेकिन सिर्फ घोषणा के साथ।
दूसरी ओर, अमूर्त वर्ग एक ऐसा वर्ग है, जिसमें कुछ विधि के साथ-साथ कुछ विधि का कार्यान्वयन हो सकता है, केवल घोषणा के साथ।
जब हम एक इंटरफ़ेस को अमूर्त वर्ग के लिए लागू करते हैं, तो इसका मतलब है कि सार वर्ग को इंटरफ़ेस के सभी तरीके विरासत में मिले हैं। के रूप में, यह सार वर्ग में सभी विधि को लागू करने के लिए महत्वपूर्ण नहीं है, हालांकि यह अमूर्त वर्ग (वंशानुक्रम द्वारा भी) की बात आती है, इसलिए सार वर्ग इंटरफ़ेस के कुछ तरीके को यहां कार्यान्वयन के बिना छोड़ सकता है। लेकिन, जब यह अमूर्त वर्ग कुछ ठोस वर्ग को विरासत में मिलेगा, तो उन्हें अमूर्त वर्ग में उन सभी को लागू करने की विधि को लागू करना होगा।


4

इंटरफ़ेस दिया:

public interface IAnything {
  int i;
  void m1();
  void m2();
  void m3();
}

यह वास्तव में जावा इसे कैसे देखता है:

public interface IAnything {
  public static final int i;
  public abstract void m1();
  public abstract void m2();
  public abstract void m3();
}

तो आप इन abstractतरीकों में से कुछ (या सभी) को अनइम्प्लीमेंटेड छोड़ सकते हैं , जैसा कि आप के मामले में करेंगेabstract क्लासेस दूसरी abstractक्लास बढ़ाते हैं ।

जब आप implementinterface, नियम कि सभी interfaceविधियों को व्युत्पन्न में लागू किया जाना चाहिए class, केवल कंक्रीट पर लागू होता हैclass कार्यान्वयन (यानी, जो abstractस्वयं नहीं है) है ।

आप वास्तव में एक बनाने की योजना है abstract classइससे बाहर, तो कोई नियम है कि कहते हैं कि आप के लिए है है implementसब interface(ध्यान दें कि इस तरह के एक मामले में यह घोषणा करने के लिए ली गई अनिवार्य है तरीकों classके रूप में abstract)


javap IAnything.classदूसरा कोड स्निपेट जनरेट करने के लिए उपयोग करना ।
18

3

जब एक सार वर्ग एक इंटरफ़ेस लागू करता है

इंटरफेसेस पर अनुभाग में, यह ध्यान दिया गया कि एक वर्ग जो एक इंटरफ़ेस को लागू करता है, उसे इंटरफ़ेस के सभी तरीकों को लागू करना चाहिए। हालांकि, यह संभव है कि एक वर्ग को परिभाषित करने के लिए जो इंटरफ़ेस के सभी तरीकों को लागू नहीं करता है, बशर्ते कि वर्ग को सार घोषित किया गया हो। उदाहरण के लिए,

abstract class X implements Y {   
    // implements all but one method of Y
}

class XX extends X {   
    // implements the remaining method in Y 
} 

इस स्थिति में, कक्षा X का सार होना चाहिए क्योंकि यह पूरी तरह से Y को लागू नहीं करता है, लेकिन कक्षा XX वास्तव में, Y को लागू करता है।

संदर्भ: http://docs.oracle.com/javase/tutorial/java/IandI/abstract.html


1

विधियों को लागू करने के लिए सार वर्गों की आवश्यकता नहीं होती है। इसलिए भले ही यह एक इंटरफ़ेस लागू करता है, इंटरफ़ेस के सार तरीके सार रह सकते हैं। यदि आप एक ठोस वर्ग में इंटरफ़ेस लागू करने का प्रयास करते हैं (अर्थात सार नहीं) और आप अमूर्त विधियों को लागू नहीं करते हैं तो कंपाइलर आपको बताएगा: या तो सार विधियों को लागू करें या कक्षा को सार घोषित करें।

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