जावा इंटरफ़ेस में निजी सदस्यों को अनुमति क्यों नहीं देता है? क्या इसकी कोई खास वजह है?
जावा इंटरफ़ेस में निजी सदस्यों को अनुमति क्यों नहीं देता है? क्या इसकी कोई खास वजह है?
जवाबों:
से जावा भाषा युक्ति, (अभिगम नियंत्रण) :
"जावा प्रोग्रामिंग भाषा किसी पैकेज या वर्ग के उपयोगकर्ताओं को उस पैकेज या वर्ग के कार्यान्वयन के अनावश्यक विवरणों के आधार पर रोकने के लिए अभिगम नियंत्रण के लिए तंत्र प्रदान करती है।"
पहुँच नियंत्रण सभी कार्यान्वयन विवरणों को छिपाने के बारे में है। एक इंटरफ़ेस में छिपाने के लिए कोई कार्यान्वयन नहीं है।
जावा 9 में, इंटरफेस में निजी तरीके संभव हैं।
Javac कंपाइलर टीम JDK के 9 b54 बिल्ड से शुरू होने वाले इंटरफेस में निजी तरीकों के लिए कंपाइलर समर्थन की उपलब्धता की घोषणा करते हुए प्रसन्न है।
JEP-213 के भाग के रूप में निजी इंटरफ़ेस विधियाँ जावा 9 का हिस्सा हैं । चूंकि जावा 8 में इंटरफेस में डिफ़ॉल्ट तरीके हो सकते हैं , इसलिए निजी तरीके साझा निजी पद्धति का उपयोग करने के लिए कई डिफ़ॉल्ट तरीकों की अनुमति देते हैं।
जावा 8 के रूप में, इंटरफेस में डिफ़ॉल्ट तरीके हो सकते हैं, और जावा 9 के रूप में, एक इंटरफ़ेस में एक निजी तरीके की अनुमति होती है जिसे केवल उसी तरीके से डिफ़ॉल्ट तरीकों से एक्सेस किया जा सकता है।
एक इंटरफेस का उपयोग एपीआई का वर्णन करने के लिए किया जाता है जो कि इंटरफ़ेस को लागू करने वाले किसी भी वर्ग द्वारा प्रदान किया जाता है। चूंकि इसकी परिभाषा के एक इंटरफेस में कोई राज्य नहीं है, इसलिए इसमें क्षेत्र के सदस्यों को घोषित करने का कोई उपयोग नहीं है।
इस तरह के इंटरफ़ेस को लागू करने का कोई तरीका नहीं होगा। एक प्रश्न का जवाब जो मैंने दृढ़ता से पेश किया है, यह बताता है कि निजी विधियों के साथ एक इंटरफ़ेस को लागू करने के लिए यह (नियमों को मौलिक रूप से बदलने के बिना) असंभव होगा - यह प्रश्न खुला है कि संरक्षित और पैकेज निजी तरीकों की अनुमति क्यों नहीं है।
class OuterClass
{
void run ( MyInterface x )
{
x . publicMethod ( ) ; // why not?
x . protectedMethod ( ) ; // why not?
x . packagePrivateMethod ( ) ; // why not?
x . privateMethod ( ) ; // why not?
}
interface MyInterface
{
public abstract void publicMethod ( ) ; // OK
protected abstract void protectedMethod ( ) ; // why not?
abstract void packagePrivateMethod ( ) ; // in interface default is public, but why not package private
private void privateMethod ( ) ; // impossible to implement
}
class MyImpl implements MyInterface
{
public void publicMethod ( ) { } // ok
protected void protectedMethod ( ) { } // no sweat
void packagePrivateMethod ( ) { } // no sweat
private void privateMethod ( ) { } // not happening
}
}
नीचे दिए गए कोड को वांछित परिणाम प्राप्त करना चाहिए। भले ही सभी विधियाँ सार्वजनिक हों, केवल सार्वजनिक विधि प्रभावी रूप से सार्वजनिक होती है। संरक्षित विधि प्रभावी रूप से संरक्षित है। पैकेजपायरशिपमैथोड प्रभावी रूप से पैकेजपाइप है। PrivateMethod प्रभावी रूप से निजी है।
class WorkAround
{
void run ( MyPrivateInterface x )
{
x . publicMethod ( ) ;
x . protectedMethod ( ) ;
x . packagePrivateMethod ( ) ;
x . privateMethod ( ) ;
}
public interface MyPublicInterface { void publicMethod ( ) ; }
protected interface MyProtectedInterface extends MyPublicInterface { void protectedMethod ( ) ; }
interface MyPackagePrivateInterface extends MyProtectedInterface { void packagePrivateMethod ( ) ; }
private interface MyPrivateInterface extends MyPackagePrivateInterface { void privateMethod ( ) ; }
}
जावा 9 में इंटरफ़ेस में निजी तरीकों की अनुमति देता है । डिफ़ॉल्ट तरीकों जावा 8. यह संभव है कि एक से अधिक डिफ़ॉल्ट तरीकों कुछ कोड साझा करना चाहते हैं है में शुरू किए गए थे, फिर यह कोड बाहरी दुनिया के संपर्क में लाने के बिना एक निजी विधि के लिए ले जाया जा सकता है। इस बग को ठीक कर दिया गया है और JDK 9 बिल्ड 54 में शुरू करके , निजी इंटरफ़ेस विधियों के लिए कंपाइलर समर्थन को फिर से जीवित किया गया है।
public interface IData{
default void processData(int data) {
validate(data);
// do some work with it
}
default void consumeData(int data) {
validate(data);
// do some work with it
}
private void validate(int data) {
// validate data
}
}
यह इसलिए है क्योंकि वे बेकार होंगे।
निजी पद्धति को कॉल करने का कोई तरीका नहीं होगा।
निजी सदस्य कार्यान्वयन विवरण हैं। एक इंटरफ़ेस सार्वजनिक भूमिका के बारे में है जो एक वर्ग ले सकता है।
निजी क्षेत्र पूरी तरह से बेकार नहीं होंगे क्योंकि अन्य क्षेत्र और आंतरिक वर्ग उन्हें एक्सेस कर सकते हैं।
हालांकि निजी तरीकों को लागू नहीं किया जा सकता था, यहां तक कि नेस्टेड कक्षाओं में भी, उन्हें लगभग बेकार बना दिया। आप उन्हें प्रतिबिंब का उपयोग करके पढ़ सकते हैं, लेकिन यह एक किनारे का मामला है।
किसी वर्ग के सदस्य जिन्हें निजी घोषित किया जाता है, उन्हें उस वर्ग के उपवर्गों द्वारा विरासत में नहीं दिया जाता है। केवल एक वर्ग के सदस्य, जिन्हें संरक्षित या सार्वजनिक घोषित किया जाता है, को एक पैकेज के अलावा अन्य उपवर्गों द्वारा विरासत में दिया जाता है, जिसमें कक्षा को घोषित किया जाता है।
स्रोत
तो आपके पास किसी भी इंटरफ़ेस में काम करने के तरीके नहीं हैं जो उस निजी गैर-अंतर्निहित क्षेत्र के साथ काम कर सकते हैं, फिर इसका अस्तित्व क्यों होना चाहिए?
हां, ऐसा नहीं कर सकते। उन सभी के लिए जो इसे क्यों नहीं करना चाहिए:
कल्पना कीजिए कि मेरे पास क्लास ए है, जो इंटरफ़ेस आई क्लास बी का उपयोग करता है, क्लास ए का विस्तार करता है, इसलिए ए में सभी इंटरफ़ेस विधियों को विरासत में मिला है।
अब, कल्पना कीजिए कि मैं कक्षा ए में एक निजी पद्धति चाहता हूं, लेकिन यह अन्य वर्गों के लिए भी अनुबंधित रूप से परिभाषित करना चाहता हूं (शायद एक वर्ग सी, जो आवश्यक रूप से कक्षा बी या ए का विस्तार नहीं करता है)।
शायद एक "इनिशियलाइज़ेशन" विधि के लिए, कि मैं एक I इंटरफ़ेस का उपयोग करके सभी वर्गों के लिए चाहता हूं। लेकिन जाहिर है कि मैं एक आरंभीकरण विधि को सार्वजनिक नहीं करना चाहता हूं .... क्योंकि इसका उपयोग केवल एक बार किया जाना चाहिए, या जैसे ही कक्षा आवश्यक हो, केवल इसलिए नहीं कि आप इसे सभी विली-निली का उपयोग करना चाहते हैं।
एकमात्र समाधान वर्कअराउंड है, या केवल इंटरफ़ेस के बिना कक्षाओं में init पद्धति को मजबूर करके।
मुझे इसका कारण समझ में नहीं आता, निश्चित रूप से, लेकिन फिर भी, यह कभी-कभी काम आ सकता है। स्पष्ट रूप से Oracle सहमत हैं क्योंकि वे JDK 9 में निजी इंटरफ़ेस विधियों की अनुमति दे रहे हैं।
मैंने जो कुछ भी किया, उसके लिए, एक साधारण बूलियन वैरिएबल रखा गया था, इस तरह इंटरफ़ेस विधि (जो निजी होनी चाहिए) को एक बार सेट होने के बाद सच (आरंभिक = सत्य) के रूप में चिह्नित किया जा सकता है। फिर जब फिर से विधि कहा जाता है तो कुछ नहीं करता है। इस तरह इंटरफ़ेस विधि को सार्वजनिक रूप से लागू किया जा सकता है, लेकिन चूंकि कंस्ट्रक्टर (मेरी कक्षा का) पहले विधि को कॉल करता है, यह चर को सही करता है, और इसलिए इसे फिर से नहीं बुलाया जा सकता है।
अन्यथा आपको एक अलग वर्कअराउंड की कोशिश करनी होगी यदि आप केवल कक्षा के आंतरिक कामकाज का उपयोग करना चाहते हैं .... शायद एक विधि स्वयं एक ध्वज को सेट और बंद कर देती है क्योंकि यह इसका उपयोग करता है। जब ध्वज गलत होता है, तो विधि कुछ भी नहीं करती है (यह तब होगा जब कोई इसे कक्षा के बाहर से बुलाएगा)। हालाँकि, जब कक्षाएं अपने तरीके से इसे बुलाती हैं, तो वे झंडे को सच में सेट करते हैं, फिर विधि को बुलाते हैं, फिर झंडे को झूठे में सेट करते हैं ??
अंत में मूक। शायद अभी के लिए बेहतर है कि बस निजी वर्ग को कक्षा में ही रखें और इंटरफ़ेस को पूरी तरह से काट दें।