2008-10-13 17 views
99

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

उदाहरण के लिए

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

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

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

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

तुम क्यों की व्याख्या कर सकते हैं?

+0

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

+0

क्या हम इसे "एडाप्टर डिजाइन पैटर्न" कह सकते हैं? अगर हमने अमूर्त वर्ग में एम 1, एम 2, एम 3 खाली शरीर रखा। तो MyMainClass उस अमूर्त वर्ग को बढ़ाता है और मैं जो भी तरीका चाहता हूं उसे ओवरराइड करने के लिए स्वतंत्र हूं, सभी विधियों को ओवरराइड करने के लिए कोई बाध्यता नहीं है। कृपया सलाह दें !! –

उत्तर

130

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

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

+0

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

+3

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

+4

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

30

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

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

1

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

2

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

5

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

Abstract classes are similar to interfaces. You cannot instantiate them, and they may contain a mix of methods declared with or without an implementation.

तो तुम क्या होता है एक अंतरफलक अन्य इंटरफेस फैली जब के बारे में सोचना। उदाहरण के लिए ...

//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); 
} 

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

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

+0

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

+0

... वास्तव में दोनों का थोड़ा सा। लेकिन निश्चित रूप से एक बात, वे तत्काल नहीं हैं। – Grateful

2

When an Abstract Class Implements an Interface

In the section on Interfaces, it was noted that a class that implements an interface must implement all of the interface's methods. It is possible, however, to define a class that does not implement all of the interface's methods, provided that the class is declared to be abstract. For example,

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

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

In this case, class X must be abstract because it does not fully implement Y, but class XX does, in fact, implement Y.

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

1

इंटरफेस को देखते हुए:

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 वर्ग का विस्तार करने के मामले में क्या करना होगा बस के रूप में।

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

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

+0

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